Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
uXs
May 3, 2005

Mark it zero!

Night Shade posted:

Caliburn Micro uses this in its PropertyChangedBase, along with some thread marshalling stuff. The ability to refactor and not have to worry about breaking all of the property changed magic strings is totally worth the tiny overhead and the slightly obscure PropertyChanged(()=>Property) instead of PropertyChanged("Property").

Another related trick: never null-check an event again. Declare them as:
code:
public event EventHandler<EventArgs> SomethingHappened = delegate{};
The empty delegate invocation is basically free, and since nothing outside your class can remove it SomethingHappened will never be null so you can omit the check.

Too much typing, use this instead: public event EventHandler<EventArgs> SomethingHappened = () => { };

Also it may be basically free, but it's not.

Adbot
ADBOT LOVES YOU

Crazy Mike
Sep 16, 2005

Now with 25% more kimchee.
A coworker asked me why I write so many static classes/methods. I said that I don't want to have to create a new object every time I want to use that method. In this case the class and methods are for running SQL queries to populate DataGridViews or update tables. She is concerned that static methods are more likely to result in memory leaks or have a bigger footprint. Is that a valid concern? Should I rewrite this class so it isn't static?

Dietrich
Sep 11, 2001

Uziel posted:

Thanks for this. I'd heard of PostSharp before but never really looked into it and even though we aren't doing anything with MVVM/WPF, this may be a big help in simplifying some cumbersome and repetitive code.

Word of warning, post sharp means post-compile stuff happens. First you build your project, then PostSharp reflects it and adds code to it.

It complicates things a bit. If you've got use for some of the other stuff PostSharp offers, then it's worth looking into, but I wouldn't add it to your toolbelt just for the INotifyPropertyChanged issue.

I was going the postsharp route until I found out about dynamic proxies and interceptors with Castle, and that's my preferred route now.

Crazy Mike posted:

A coworker asked me why I write so many static classes/methods. I said that I don't want to have to create a new object every time I want to use that method. In this case the class and methods are for running SQL queries to populate DataGridViews or update tables. She is concerned that static methods are more likely to result in memory leaks or have a bigger footprint. Is that a valid concern? Should I rewrite this class so it isn't static?

Your co-worker's explanations are bullshit, but non-static classes have a lifecyle which can be valuable for managing things such as SQL connections, and you can have classes implement interfaces and be injected into the objects that call your query methods, so that you can mock the SQL call for unit testing purposes.

Consider this.

C# code:
public interface ICustomerQuery {
  Customer GetCustomerById(int id)
}

public class SqlCustomerQuery : ICustomerQuery {
  public Customer GetCustomerById(int id) { /* implementation */ }
}

public class CustomerThingy {  
  private ICustomerQuery _custQuery;

  public CustomerThingy(ICustomerQuery custQuery)
  {
    _custQuery = custQuery;
  }

  public bool SelectedCustomerIsActive()
  {
    var customer = _custQuery.GetCustomerById(selectedCustomerId);
    return !customer.disabled && customer.Orders.Max(o => o.OrderDate) > GetDate().SubtractDays(30);
  }
}
Now, if you want to test your CustomerThingy's Selected Customer is Active method, you can construct an instance of it with a mocked ICustomerQuery that returns a customer with known data. You can't really do this if your CustomerThingy is calling the static method of a named class. Without this kind of structure, you would have to know a record in your database that would satisfy the requirements of your test.

Dietrich fucked around with this message at 18:10 on Jul 10, 2013

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

Dietrich posted:

you would have to know a record in your database that would satisfy the requirements of your test.

And then you have a brittle test that will break for reasons other than the code being broken, which is a testing no-no.

Static methods are okay when:
  • They do not create any sort of global state (singletons are anathema to good testing practices!)
  • They use no external dependencies (databases, web services, current date/time, the file system, etc)

Basically, they're okay if they're responsible for "turning X into Y" or "mutating an instance of X in some way".

gariig
Dec 31, 2004
Beaten into submission by my fiance
Pillbug

Crazy Mike posted:

A coworker asked me why I write so many static classes/methods. I said that I don't want to have to create a new object every time I want to use that method. In this case the class and methods are for running SQL queries to populate DataGridViews or update tables. She is concerned that static methods are more likely to result in memory leaks or have a bigger footprint. Is that a valid concern? Should I rewrite this class so it isn't static?

Dietrich already covered it from a technical perspective. Lots of statics are fine as long as you aren't doing something careless like holding onto disposable objects from a static constructor or Win32 handles. However, the problem with static classes/methods is they are global and globals are evil. For example, if your data access is through static methods any part of your application could be touching your database (views, controllers, model objects, etc) creating unneeded coupling. If your data access is an object that needs to be passed into a class (inversion of control) you can see which classes are coupled to a dependency.

Static classes can be helpful for items that are pure functions with no side effects or other dependencies. The usual example would be string helper functions. I don't mind parts of my application taking a dependency on my left/right/substring functions. Plus I can make them extension methods hanging off the string function.

ljw1004
Jan 18, 2005

rum

gariig posted:

However, the problem with static classes/methods is they are global and globals are evil... Static classes can be helpful for items that are pure functions with no side effects or other dependencies. The usual example would be string helper functions. I don't mind parts of my application taking a dependency on my left/right/substring functions. Plus I can make them extension methods hanging off the string function.

To be clear, your link about why global is evil was only about why global state is evil. It's not an argument against global methods themselves.

The global methods need not even be "pure" -- for instance, Array.Clear(...) modifies its argument, so it's not pure, but it doesn't touch any global state. As long as the global methods only modify their parameters or produce a return value, they're fine.


If our architecture is primarily concerned with objects (and their lifetimes and states), then sure it makes sense to have methods on objects which modify those objects.

But there are a whole load of lovely program designs with plain minimal objects that have few methods on them, and instead the methods are all global methods that operate the objects passed as arguments.

Especially if our architecture is primarily about processes, e.g. using a lot of async, then we'll probably adopt a functional style and have immutable objects and lots of global functions. (but still no global state).

epswing
Nov 4, 2003

Soiled Meat
WPF question. I have a custom control similar to the following.

C# code:
public class MyTextBox : TextBox
{
    public MyTextBox(MyTextBox)
    {
        DataObject.AddPastingHandler(this, PastingHandler);
    }

    private void PastingHandler(object sender, DataObjectPastingEventArgs e)
    {
        e.CancelCommand();
    }
}
In this example, MyTextBox just prevents pasting. It does this by adding a pasting handler. If I use this control in a Window, will this handler prevent the GC from collecting the Window after it closes? (Aside, how can I answer the previous question definitively, that is, how does one track down WPF memory leaks created by 3rd party controls?)

I'm 99% sure I need to execute DataObject.RemovePastingHandler(this, PastingHandler); somewhere. If I make MyTextBox IDisposable and put RemovePastingHandler in a Dispose method, WPF isn't going to call this automatically. I could get the window to call Dispose on all the MyTextBox instances, sounds like that would work, but is that really The Right Way? But where else could RemovePastingHandler go? The MyTextBox finalizer?

I'm seeing lots of StackOverflow and MS Connect questions and answers about this, and haven't found any great answers.

Dietrich
Sep 11, 2001

epalm posted:

WPF question. I have a custom control similar to the following.

C# code:
public class MyTextBox : TextBox
{
    public MyTextBox(MyTextBox)
    {
        DataObject.AddPastingHandler(this, PastingHandler);
    }

    private void PastingHandler(object sender, DataObjectPastingEventArgs e)
    {
        e.CancelCommand();
    }
}
In this example, MyTextBox just prevents pasting. It does this by adding a pasting handler. If I use this control in a Window, will this handler prevent the GC from collecting the Window after it closes? (Aside, how can I answer the previous question definitively, that is, how does one track down WPF memory leaks created by 3rd party controls?)

I'm 99% sure I need to execute DataObject.RemovePastingHandler(this, PastingHandler); somewhere. If I make MyTextBox IDisposable and put RemovePastingHandler in a Dispose method, WPF isn't going to call this automatically. I could get the window to call Dispose on all the MyTextBox instances, sounds like that would work, but is that really The Right Way? But where else could RemovePastingHandler go? The MyTextBox finalizer?

I'm seeing lots of StackOverflow and MS Connect questions and answers about this, and haven't found any great answers.

The garbage collector will clean it up eventually because nothing will reference it. If you aren't making hundreds of these things then I wouldn't worry about it. If you are, then implement I disposable, remove the handler on disposal, and dispose of it when you close the host form.

Sedro
Dec 31, 2008
WPF does a good job managing the lifetime of its controls. You should never have to implement IDisposable. If you are subscribing to non-WPF events (DataObject.PastingEvent is a RoutedEvent) you can use Loaded/Unloaded instead of the ctor/dispose/finalizer pattern.

I do check that my view-models are being disposed properly. Sometimes a UIElement will hang on to a view-model reference through binding. Usually I'll open and close the UI say 100 times, then run !dumpheap -type my.fully.qualified.ViewModel, then run !gcroot if they aren't being GC'd properly.

BTW, I would use an attached property instead of extending the TextBox.

Night Shade
Jan 13, 2013

Old School

uXs posted:

Too much typing, use this instead: public event EventHandler<EventArgs> SomethingHappened = () => { };

Also it may be basically free, but it's not.

It isn't totally free, but I ran some timing loops in linqpad on an i7-2600:

quote:

null check unsubscribed - 100,000,000 iterations: 00:00:00.3041283 (3.041283 ns/iteration)
null check subscribed - 100,000,000 iterations: 00:00:00.4259502 (4.259502 ns/iteration)
null check double subscribed - 100,000,000 iterations: 00:00:01.4567414 (14.567414 ns/iteration)

default implementation - 100,000,000 iterations: 00:00:00.3956589 (3.956589 ns/iteration)
default implementation subscribed - 100,000,000 iterations: 00:00:01.4991489 (14.991489 ns/iteration)
where "default implementation" is doing that trick, and subscribed is where an external handler is registered.

To be honest if you're trying to nickel and dime over less than ten nanoseconds, .NET is probably not an appropriate environment for whatever you're doing.

Edit: and the added memory pressure is best measured in individual bytes.

uXs
May 3, 2005

Mark it zero!
Still, I'm technically correct, and we all know that's the best kind of correct.

zokie
Feb 13, 2006

Out of many, Sweden
In this WPF-project I'm working on I have a basic list of stuff, if you double-click an item or whatever a dialog appears that let's you edit it. Said dialog is opened from the code-behind of the view containing the list, in the dialog I attach a click handler to the Save-button which closes the dialog with DialogResult = true. I check this in the view that opened the dialog and if it's set to true (changes made) I update the list from the server.

My problem is this, using TPL the Save-command called on the ViewModel of the dialog returns control super fast, too fast :v:. The view gets the dialog result and updates itself before the ViewModel was done saving changes...

I already have an ICommandViewModel interface for ICommands on ViewModels, I figured I should implement an CommandExecuted-Event and close the dialog by subscribing to it instead? But I wan't the dialog to disappear as soon as possible, hide and then close?

What are your thoughts?

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

zokie posted:

In this WPF-project I'm working on I have a basic list of stuff, if you double-click an item or whatever a dialog appears that let's you edit it. Said dialog is opened from the code-behind of the view containing the list, in the dialog I attach a click handler to the Save-button which closes the dialog with DialogResult = true. I check this in the view that opened the dialog and if it's set to true (changes made) I update the list from the server.

My problem is this, using TPL the Save-command called on the ViewModel of the dialog returns control super fast, too fast :v:. The view gets the dialog result and updates itself before the ViewModel was done saving changes...

I already have an ICommandViewModel interface for ICommands on ViewModels, I figured I should implement an CommandExecuted-Event and close the dialog by subscribing to it instead? But I wan't the dialog to disappear as soon as possible, hide and then close?

What are your thoughts?

From a usability perspective, if a "save" operation is occurring that will change the data being displayed, it makes sense to notify the user that the save is occurring and close the dialog after the save is completed. Otherwise, you return to the parent form, and the user assumes that everything is saved and they continue working. Then, a few seconds later, the displayed data changes and it's disruptive and confusing. And what happens if the save fails for some reason?

It would probably be easiest to just await the task and put up a message for the user that says "Saving..." or something along those lines.

Sab669
Sep 24, 2009

edit; nevermind....

Sab669
Sep 24, 2009

Don't mean to double post, but now I do have a question. We have a ComboBox control that we made that has a "Top Most Item" property (just something to appear at the top of the list, before all other actual list items). In the Design view of the control itself, we do set a default value for this property, so that way when we use the control we don't need to configure that ourselves since 9/10 times it's the same.

I'm on that 1/10 instance where I don't want that default property value, so I select my combobox on the windows form and change the Top Most Item property. Then I run the program and it reverts back to the original value. What step am I missing? :v:

Unfortunately the guy who made the control is off for the next week and a half and I'm able to get the source, just the dll :psyduck:

Sab669 fucked around with this message at 19:11 on Jul 11, 2013

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

Sab669 posted:

Unfortunately the guy who made the control is off for the next week and a half and I'm able to get the source, just the dll :psyduck:

Uhh, why is all of your source code not in source control? You should start raising a stink about that, it's totally unacceptable.

Try ILSpy and decompile the assembly, then you can figure out what it's doing wrong.

Rooster Brooster
Mar 30, 2001

Maybe it doesn't really matter anymore.

Uziel posted:

Thanks for this. I'd heard of PostSharp before but never really looked into it and even though we aren't doing anything with MVVM/WPF, this may be a big help in simplifying some cumbersome and repetitive code.

PostSharp is really cool and powerful, but I hit some of its "free" license restrictions pretty quickly. There are other options like Fody out there. Castle Dynamic Proxy was one other.

CapnAndy
Feb 27, 2004

Some teeth long for ripping, gleaming wet from black dog gums. So you keep your eyes closed at the end. You don't want to see such a mouth up close. before the bite, before its oblivion in the goring of your soft parts, the speckled lips will curl back in a whinny of excitement. You just know it.
So you know how you guys told me that if I wanted unit testing in a web service, I should move all the code to a code-behind library, have the web service reference the library, and I could test that? I did that. Unit testing works awesome. Now I have a whole new set of problems.

First I set the code up like this:
code:
public class ServiceCode
{
     a few global variables;

     public ServiceCode(bool liveOrDev)
     {
          constructor logic based on liveOrDev;
     }

     public lots of functions(whatever)
     {
          returns the whatever;
     }
}
code:
public class WebService : System.Web.Services.WebService
{
     public ServiceCode service;

     public WebService()
     {
         constructor logic, determines live or dev;
         service = new ServiceCode(liveOrDevBool);
     }

     [WebMethod]
     public whatever function(whatever)
     {
          return service.whatever function(whatever);
     }
}
This worked for a few hours, and then the service would start throwing System.OutOfMemoryException left and right. I figured the only logical conclusion was that I had a memory leak in the new code, and since the only change was creating the code library in the first place, the code library had to be the memory leak. It must not be being disposed after each call. So I changed WebService a bit. I commented out the declaration of ServiceCode service and changed each web method to this:
code:
[WebMethod]
public whatever function(whatever)
{
     whatever result = new whatever;

     using (ServiceCode service = new ServiceCode(liveOrDevBool))
     {
          result = service.whatever(whatever);
     }
     
     return result;
}
The code immediately bitched me out because ServiceCode didn't extend IDisposable. Aha, I thought! I was clearly right about it being the memory leak. It couldn't be disposed! I had ServiceCode extend IDisposable and added a Dispose method:
code:
public void Dispose()
{
     releasing all the global variables;
}
Works great the first time, but every service call after that throws the same error:
code:
System.ObjectDisposedException: Safe handle has been closed
   at System.Threading.WaitHandle.WaitOneNative(SafeWaitHandle waitHandle, UInt32 millisecondsTimeout, 
Boolean hasThreadAffinity, Boolean exitContext)
   at System.Threading.WaitHandle.WaitOne(Int64 timeout, Boolean exitContext)
   at System.Threading.WaitHandle.WaitOne(Int32 millisecondsTimeout, Boolean exitContext)
   at System.Threading.WaitHandle.WaitOne()
I do some Googling on the exception and apparently it means that I'm disposing of something I shouldn't have (I also got a lot of stuff about IO ports in my searches, which were clearly not applicable). It's crashing at a mutex.WaitOne() call (I trace the code to confirm this). I do have _mutex.Close() in my Dispose method... maybe I shouldn't? I comment it out and try again. Same issue. Okay, fine. I comment out everything in Dispose(), leaving it empty. Same issue.

I'm at my wits' end trying to figure out just what the loving hell I'm disposing or not disposing that I should be doing the opposite. Here's literally all the code in the entire project that uses mutex.
code:
//in general declarations
private static Mutex _mutex = new Mutex();

//in constructor logic
if (_sessionFactory == null)
{
     _mutex.WaitOne();
     if (_sessionFactory == null)
     {
          _sessionFactory = createISeriesSessionFactory(liveOrDev);
     }
     _mutex.ReleaseMutex();
}
The sessionFactory is a FluentNHibernate thing, it doesn't use mutex itself. If I take out the mutex stuff altogether, the code starts working fine (well, multiple calls work; I haven't tested it to see if the OutOfMemory exceptions come back), but I'd rather not -- my predecessor put that in and I'm not entirely sure why he did, so I'm assuming there's a good reason and it shouldn't be removed.

By the way, sorry for all the psuedo-code and summarizing, but there's 2000 lines of code in the real project. I'm not copying it for realsies.

CapnAndy fucked around with this message at 21:35 on Jul 11, 2013

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

CapnAndy posted:

So you know how you guys told me that if I wanted unit testing in a web service, I should move all the code to a code-behind library, have the web service reference the library, and I could test that? I did that. Unit testing works awesome. Now I have a whole new set of problems.

First I set the code up like this:
code:
public class ServiceCode
{
     a few global variables;

     public ServiceCode(bool liveOrDev)
     {
          constructor logic based on liveOrDev;
     }

     public lots of functions(whatever)
     {
          returns the whatever;
     }
}

This is bad. You don't want to have "live or dev" be controlled by a boolean flag. Fields in your service also sound iffy. What on earth is your service doing that it has state? The exception would be for anything injected via the constructor.

What does that boolean flag control?

quote:

code:
public void Dispose()
{
     releasing all the global variables;
}
Works great the first time, but every service call after that throws the same error:
code:
System.ObjectDisposedException: Safe handle has been closed
   at System.Threading.WaitHandle.WaitOneNative(SafeWaitHandle waitHandle, UInt32 millisecondsTimeout, 
Boolean hasThreadAffinity, Boolean exitContext)
   at System.Threading.WaitHandle.WaitOne(Int64 timeout, Boolean exitContext)
   at System.Threading.WaitHandle.WaitOne(Int32 millisecondsTimeout, Boolean exitContext)
   at System.Threading.WaitHandle.WaitOne()

Well, first off, you're not implementing IDisposable properly. Try to implement it properly and see if that solves the issue.

uXs
May 3, 2005

Mark it zero!

Ithaqua posted:

This is bad. You don't want to have "live or dev" be controlled by a boolean flag. Fields in your service also sound iffy. What on earth is your service doing that it has state? The exception would be for anything injected via the constructor.

What does that boolean flag control?


Well, first off, you're not implementing IDisposable properly. Try to implement it properly and see if that solves the issue.

Or even better, don't implement it at all. Just wrap whatever you have to dispose in a 'using' block.

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

uXs posted:

Or even better, don't implement it at all. Just wrap whatever you have to dispose in a 'using' block.

I'm assuming that some of those fields he's talking about implement IDisposable themselves.

Really, the code should look like this:

code:
public interface IServiceCode
{
	lots of functions(whatever);
}
public class ServiceCode : IServiceCode
{
     a few global variables;

     public lots of functions(whatever)
     {
          returns the whatever;
     }
}
code:
public class WebService : System.Web.Services.WebService
{
     private IServiceCode service;

     public WebService(IServiceCode service)
     {
	this.service = service;
     }
     
     public WebService() : this(new ServiceCode()) { }

     [WebMethod]
     public whatever function(whatever)
     {
          return service.whatever function(whatever);
     }
}
That will let you create and inject a mock implementation of your service logic for testing purposes. The "live or dev" boolean is terrible.

Orzo
Sep 3, 2004

IT! IT is confusing! Say your goddamn pronouns!
Having a class with 'global variables' (I assume you mean 'static') that is Disposable where the Dispose method releases those static variables is a terrible idea. What if there were two instances of the class and the first one got Disposed and the second one was still in use?

Uziel
Jun 28, 2004

Ask me about losing 200lbs, and becoming the Viking God of W&W.
Before I go this route, I wanted to see if there was an easier way to do this. I'm exploring some ideas for a personal project and it relies on data from a site that would need to be scraped. I'll use the HtmlAgility pack to read the data, but I need to be able to post and change what the values posted are.

This is the site. Yes, the official ranking site for a fringe sport is in class ASP. =(
http://nasgaweb.com/dbase/main.asp

Scrolling down to "Rankings", then "Select class for overall ranking" and picking Pro and 2013 as the form values. The form tag is
code:
<form action="rank_overall.asp" method="POST">
In regular browser, this redirects me to http://nasgaweb.com/dbase/rank_overall.asp with the results displayed.
I used Fiddler to see how the values are being passed:
"class=Pro&rankyear=2013&x=26&y=10"

So I tried navigating to http://nasgaweb.com/dbase/rank_overall.asp?class=Pro&rankyear=2013&x=26&y=10 and I get a 404 page:
http://nasgaweb.com/dbase/rank_overall5.asp?class=&year=

If I fill those values in like this:
http://nasgaweb.com/dbase/rank_overall5.asp?class=Pro&year=2013&x=26&y=10

I still get the 404.

This page shows that I can create a session browser class and do it that way but I wanted to make sure I wasn't missing something easier/more obvious.

Edit: Apparently the only reason I posted this was so I could figure it out on my own 30 mins later. The below is good enough to start with:
code:
static void Main(string[] args)
        {
            //"class=Pro&rankyear=2013&x=26&y=10"
            //classes: Pro, All+Women, All+Amateurs, All+Masters, All+Lightweight
            const string classType = "Pro";
            using (WebClient client = new WebClient())
            {
                NameValueCollection formValues = new NameValueCollection
                    {
                        {"class", classType},
                        {"rankyear", "2013"},
                        {"x", "26"},
                        {"y", "10"}
                    };
                byte[] byteArray = client.UploadValues("http://nasgaweb.com/dbase/rank_overall.asp", formValues);
                string rawHtml = Encoding.ASCII.GetString(byteArray);
                bool isAthleteInResults = rawHtml.Contains("Matt&nbsp;Vincent");
            }

Uziel fucked around with this message at 22:45 on Jul 13, 2013

diadem
Sep 20, 2003
eet bugz
If you run Windows 7 and the latest Windows Update is preventing you from loading solutions with Visual Studio 2012 Ultimate, upgrade Visual Studio to the latest service pack update and your solutions should load again.

ljw1004
Jan 18, 2005

rum
Just curious - has anyone here tried the VS2013 preview yet?
http://www.microsoft.com/visualstudio/eng/2013-preview

Any feedback or comments you want me to pass on to the team? (also it has "send-a-smile/frown")


Personally, I'm most proud about how the callstack window now works with async...
http://mdavey.wordpress.com/2013/06/28/vs2013-async-debugging/

Posting Principle
Dec 10, 2011

by Ralp
I don't normally do .NET stuff, but I'm digging into a fairly big WPF project right now, and having everything in one project is getting to be a bit much.

The basic set up I have right now is:
- the XAML, which is bound to some model classes
- the models, using ObservableCollections and INotifyProperty changed to bind to the xaml
- some controllers, which get Commands from the xaml and modify the model, as well as loading and persisting it

Should these things be extracted into separate assemblies? If these are going to be separate assemblies, what's the preferred Windows way of distributing an exe and its necessary dlls? Is MVVM something I should start caring about?

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

Jerry SanDisky posted:

I don't normally do .NET stuff, but I'm digging into a fairly big WPF project right now, and having everything in one project is getting to be a bit much.

The basic set up I have right now is:
- the XAML, which is bound to some model classes
- the models, using ObservableCollections and INotifyProperty changed to bind to the xaml
- some controllers, which get Commands from the xaml and modify the model, as well as loading and persisting it


quote:

Should these things be extracted into separate assemblies?
Maybe. If you're unit testing the viewmodel, absolutely.

quote:

If these are going to be separate assemblies, what's the preferred Windows way of distributing an exe and its necessary dlls?

An installer of some kind (ClickOnce, MSI, WIX, whatever).

quote:

Is MVVM something I should start caring about?

Yes. If you're doing WPF without MVVM, you're doing WPF wrong, although it sounds like you're doing MVVM or something close to it. The goal is "separation of concerns". MVVM is the easiest way to do that with WPF.

Dietrich
Sep 11, 2001

Jerry SanDisky posted:

Should these things be extracted into separate assemblies? If these are going to be separate assemblies, what's the preferred Windows way of distributing an exe and its necessary dlls? Is MVVM something I should start caring about?



For our in house development we just put the assembly and .dlls in a folder in our share drive (one folder per app) and I have written a program that copies them all down to the user's computer then runs the executable. We distribute shortcuts that call this program with the appropriate args.

The advantage of this is that we only need to copy files that are changed when we release a patch, and we don't have to deal with creating an installer or clickonce being the complete bastard it tends to be.

Posting Principle
Dec 10, 2011

by Ralp
Thanks. Are there any quick resources for doing "proper" MVVM? I know VS2010 express lacked support for MSI installer projects, is that something I can do with 2012?

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



I'm having trouble getting a WCF web service to tell me why it can't run. The only output when I hit it is a message about an InternalServiceFault that tells me to enable IncludeExceptionDetailInFaults or turn on tracing, both of which are already enabled on the development config. Nothing is written to the trace log. The debugger isn't seeing any exceptions (Just My Code is disabled). Sometimes Session_Start gets run but sometimes it only makes it to BeginRequest (both of which are empty), but then the error gets kicked out without any of my code getting run. If it makes it to Session_Start and I leave the debugger open long enough, I'll see it hit Session_End. What else can I do to try to get any useful information out of this loving thing?

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

Munkeymon posted:

I'm having trouble getting a WCF web service to tell me why it can't run. The only output when I hit it is a message about an InternalServiceFault that tells me to enable IncludeExceptionDetailInFaults or turn on tracing, both of which are already enabled on the development config. Nothing is written to the trace log. The debugger isn't seeing any exceptions (Just My Code is disabled). Sometimes Session_Start gets run but sometimes it only makes it to BeginRequest (both of which are empty), but then the error gets kicked out without any of my code getting run. If it makes it to Session_Start and I leave the debugger open long enough, I'll see it hit Session_End. What else can I do to try to get any useful information out of this loving thing?

By "trace logs" do you mean IIS logs? If not, did you check those?

What about the event viewer?

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



By trace log I mean Microsoft.Practices.EnterpriseLibrary.Logging.TraceListeners.FlatFileTraceListener set up in the loggingConfiguration section of the web.config. There's nothing in my IIS events and all IIS is recording in its log files is the fact that someone got a 500 response when they hit the service URL.

Milotic
Mar 4, 2009

9CL apologist
Slippery Tilde
Try adding this to your web.config - it's what I use when WCF is being a pain. Don't leave it on in production though!

code:
   <system.diagnostics>
      <sources>
            <source name="System.ServiceModel" 
                    switchValue="Information, ActivityTracing"
                    propagateActivity="true">
            <listeners>
               <add name="traceListener" 
                   type="System.Diagnostics.XmlWriterTraceListener" 
                   initializeData= "c:\log\Traces.svclog" />
            </listeners>
         </source>
      </sources>
   </system.diagnostics>

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Ugh, I'm an idiot - all that was set up in the config. Twice, unlike most of our projects, which is why I was expecting all of the error information to end up in a different file.

Hope this makes someone laugh: all of the errors were "Could not load file or assembly 'Microsoft.Practices.EnterpriseLibrary.Logging..."

Some day this loving project will build and run without manual intervention :\

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug

Munkeymon posted:

Hope this makes someone laugh: all of the errors were "Could not load file or assembly 'Microsoft.Practices.EnterpriseLibrary.Logging..."

:cawg:

Ahh, I love it when the error handling is causing an error.

Uziel
Jun 28, 2004

Ask me about losing 200lbs, and becoming the Viking God of W&W.
So earlier on this page, I said I was working on a hobby project to scrape data from a website. I also had contacted the owner to see if I could get read access rather than reinvent the wheel. He actually got back to me but I'm not entirely sure how to respond to this:

quote:

I think it’s great that you want to do this. I like your idea, if it works out maybe we could make it more general and be able to access any type of data from the database.

I am not familiar with apps and how they access information such as this so I will need your help understanding this. No API exists since this is a custom database application built on older technology (ASP & MS Access Database). What would an app need to be able to retrieve information? Could I just set up a web page with the appropriate database scripts that the app could call? This is kind of how it works an called Pingdom that I use to keep track of any outages that may occur on the site. After the database script is run, it sends data in xml format back to the script.

I'm thinking I might as well just stick to scraping the data using a webclient and the htmlagilitypack than open this can of worms. :|

wwb
Aug 17, 2004

There is a really easy out here -- see if he can setup a way for you to get a copy of the access Db. It ain't good at much, but being transportable in a single file isn't bad. With a copy of the DB you could probably turn around and hand him the scripts that spit out the XML or whatever you want.

And yes I'll publicly admit I made a number of access backed web apps though I was young and needed the money and didn't know any better.

PS: the model is valid, ask all the cool kids developing against sqllite.

wwb fucked around with this message at 00:57 on Jul 18, 2013

New Yorp New Yorp
Jul 18, 2003

Only in Kenya.
Pillbug
I'm working on a hobby project and I've done something that's either clever or dumb, but I can't decide which.

The application receives messages over a network socket. The messages are in a regular, parseable format. Each message, when parsed, ultimately ends up represented by its own class that implements the IReceivableMessage interface, in order to expose the message's data as properties. There are ISendableMessages as well, but those don't come into play here. I want to have a central place where I can control the message parsing logic, so I started by creating a ReceivableMessageFactory.

It looks like this:
C# code:
public static class ReceivableMessageFactory
{
    public static IReceivableMessage ParseMessage(string message)
    {
        if (message.StartsWith("WHATEVER"))
        {
            return new FooMessage(message); // logic for actually parsing this particular type of message lives in the class itself, irrelevant here
        }
        return new UnknownMessage(message);
    }
}
So, cool. We pass a string to the messagefactory and it spits something out.

At this point, it has to fire off the correct event. I absolutely hate the idea of doing this a million times for each type:
C# code:
IReceivableMessage message = ReceivableMessageFactory.ParseMessage("WHATEVER");
if (message is FooMessage && OnFooMessage != null) 
{
	OnFooMessage(this, (FooMessage)message);
}
So, I decided to get clever.
code:
private bool TryPropogateMessage<T>(IReceivableMessage message, EventHandler<T> e)
{
    if (!(message is T))
    {
        return false;
    }

    if (e != null)
    {
        e(this, (T)message);
    }

    return true;
}

private void ParseMessage() 
{
    IReceivableMessage message = ReceivableMessageFactory.ParseMessage("WHATEVER");
    var propogationAttempts = new List<Func<bool>> 
    {
        () => this.TryPropogateMessage(message, this.OnFooMessage),
        () => this.TryPropogateMessage(message, this.OnUnknownMessage) //etc 
    };
    
    propogationAttempts.Any(attempt => attempt());
}
I feel like that's cleaner, but I also feel like I'm committing some sort of minor atrocity.

I'm considering going back and creating a more generic Message class that exposes the properties as dictionary keys, but I'm trying to keep my public-facing API very clean and easy-to-use.

New Yorp New Yorp fucked around with this message at 01:04 on Jul 18, 2013

His Divine Shadow
Aug 7, 2000

I'm not a fascist. I'm a priest. Fascists dress up in black and tell people what to do.
Is there some LINQ equivalent to this Mysql sorting ability?

ORDER BY FIELD(FieldName,"heyo", "this is second", "third")

Essentially I can make a custom sorting order based on what said field contains, can be numbers, can be strings.

Adbot
ADBOT LOVES YOU

SirViver
Oct 22, 2008

His Divine Shadow posted:

Is there some LINQ equivalent to this Mysql sorting ability?
Assuming you're talking about LINQ to objects, you can sort of do it if the data structure you're querying has a way to access fields via string (e.g., a string indexer). A DataTable would for example be such a structure. I guess technically it would also be possible to achieve that on normal POCOs via reflection, but that sounds very ugly and slow. One limitation this has is that the dynamic columns ordered by must all have the same data type, though I don't know how MySQL behaves in that regard either.

Example: http://dotnetpad.net/ViewPaste/Y8o3Nl1WYUKPO7grljNqXA

  • Locked thread