XNA AI Talk

Tomorrow night (Thursday, 2/21/08) is the next XNA Twin Cities User Group meeting and I will be giving a presentation on the MinMax algorithm in Drop In. It should be pretty fun, there will be some pizza and swag (including some xbox games) and a few other speakers talking about some other interesting AI topics. If you’re in the area you should definitely stop in and learn about XNA!

Here is the main link http://www.twincitiesxnausergroup.com/

And be sure to RSVP so we can guage how many people will be there and get the appropriate amount of pizza.

NBusiness 3 Updates

I’ve been working on NBusiness a little bit over the weekend. I’ve decided to create a Curried API using extension methods for the CodeDom to speed along template creation. Here is an example of what I have so far.

CodeMethodReferenceExpression onPropertyChanged =
 new CodeMethodReferenceExpression(null, “OnPropertyChanged”);
 
CodeMemberProperty memberProperty = new CodeMemberProperty();
memberProperty.Name = field.Name.ToPascalCase();
memberProperty.Type = new CodeTypeReference(field.Type);
 
memberProperty.Get()
.Return(memberField.Reference());
memberProperty.Set()
.If(             
    memberField.Reference().NotEqualTo(memberProperty.SetValue()))
.Then(
   memberField.Reference().Assign(
      memberProperty.SetValue()),
      onPropertyChanged.Invoke(memberProperty.Name));
Trust me, as ugly as the above seems it’s still a million times better than doing it all the way it was originally written. Hopefully this will mature and get better over time as well. Here is an example of the code it produces.
private int Aid {
 get {
   return _aid;
}
 set {
   if ((_aid != value)) {
      _aid = value;
      OnPropertyChanged(“Aid”);
    }
}
}
Secondly I have been polishing and simplifying the model framework that comes with NBusiness. I have been working to create an abstract DataAccess API that can easily produce any type of query. Here is an example of how you might insert a new model with the next version of NBusiness.
MockModel model = new MockModel();
model.Name = “testinsert”;
model.Save();
This is as normal and will end up calling into MockModel’s “InsertModel” method which may be implemented like so
protected override void InsertModel(IQuery query)
{
query.Insert().Into(
    MockModel.Database.Table,
    MockModel.Database.Name).Values(“@Name”);
query.Go();
query.Parameter(“@Id”).Direction = ParameterValueDirection.Output;
query.Parameter(“@Name”).Value = Name;
query.Load += loader =>
{
   Id = (int)query.Parameter(“@Id”).Value;
};
}
The DataBase.Table and DataBase.Name members are code generated, static ITable and IColumn fields based on your E# model definition. The query object will be passed up to parent objects and down to child objects and will be passed into an abstract provider which will use it to generate SQL and call your database. The IQuery object actually comes from your IDatabaseProvider and may abstract it to work with different databases. My theory at this point is that you could actually parse the query object anyway you like in the IDatabaseProvider and with a little manual work you could even get it working across a webservice.
Here is my MockDatabaseProvider for my unit tests. The provider interface is much simpler with this new technique.
class MockDatabaseProvider : IDatabaseProvider
{
#region IDatabaseProvider Members
 
 public IQuery Query()
{
    return new SqlQuery();
}
 
 public ITable Table(string name)
{
   return new SqlTable(name);
}
 
 public void Execute(IQuery query)
{
   MethodCall.Calls.Add(new MethodCall(
      “Execute”,
      new { Name = “query”, Value = query }));
 
   SqlQuery sqlQuery = query as SqlQuery;
           
    // Simulate setting the identity parameter after an insert
    IParameterValue id = sqlQuery.Parameters.FirstOrDefault(
      v => v.Name == “@Id”);
   
    if (id!=null && id.Direction == ParameterValueDirection.Output)
    {
      id.Value = 100;
    }
 
    sqlQuery.OnLoad(new MockLoader());
}
 
#endregion
}

Offline Editing With TFS Integrated Source Control

I am a big fan of TFS. I have been using it for a while both at work and through codeplex. I have used several other source control systems including CVS, SVN, VSS and Star Team. I can say without equivocation that TFS is the best hands down, my second favorite is SVN which is a really great source control system as well.

Up until today there was two areas where I would say that SVN beats TFS and makes it worth using. The first is price; SVN is free while TFS is expensive, so it depends on your budget and your need for quality. If you are working on a public project you might as well go with codeplex because you’ll get a great source control system for free along with wiki pages, forums and issues management.

The second area is the ability to work on your project offline. SVN is perfectly designed with this concept in mind, you edit offline to your hearts content then the next time you’re online you fetch and merge everything and then check it in. Very simple but with TFS, since you’re integrated, once you are offline you loose the ability to keep track of what items you’re checking out and working on then the next time you go back online you end up needing to checkout stuff as a guess and it will also cause your integrated source control settings to get messed up it is very kludgy and annoying.

Well today I ran into a bug in TFS integrated source control and looked it up on the MSDN forums to see what the answer was. I had a situation where everytime I opened my TFS bound project it would be offline and I would have to rebind to the source control server every single time. Verrry annoying. Well after reading on the forums I found out that integrated projects actually have an “offline” mode built in and by right clicking on an offline solution node in the solution explorer tree you can select the “Go Online” command which will reconnect you to the server. What’s cool is that it actually keeps track of your offline edits, adds and deletes and will prompt you to check out the items when you go online! This is really cool, it effectively solves the offline problem of TFS integrated source control. Now I’d say SVN only has one advantage.

Of course in Visual Studio 2008 pre SP1 there is a bug here, and if I had some feedback for the TFS team I would reccommend that they either automatically “Go Online” when a bound solution is opened and the machine is connected or have some sort of icon somewhere to attract attention to the fact that this feature even exists. I have a feeling it’s been there for a while but I simply didn’t know about it. Maybe give the solution node a “disconnected” icon? Maybe keep all of the regular source control icons still? Something here is a little unintuitive.

So the tip of the day is if you’re working on your laptop with a TFS project and you suddenly go offline, don’t worry! Next time you’re online just right click your solution and select “Go Online” and you’re back in business.

WPF and MVC

Today I spent some time looking at how to organize my WPF application to use a Model View Controller design pattern. I ended up getting it to work fairly well but I am pretty dissapointed in the lack of support for this model directly.

Specifically I got hung up on the limitations around the ObjectDataProvider class. This is a DataSourceProvider object you can use to bind your controls against. You have two options with this data provider, you either specify an ObjectType or an ObjectInstance. If you specify the ObjectType then you end up with complete design time support for databinding against this provider, which is a wonderful thing in Blend 2. However, if you do this then the ObjectDataProvider will take it upon itself to create your instance based on the Type information you provided… which does not work if you want to specify an interface or an abstract class. Using the ObjectInstance approach will also give you design time support if you’re the instance you provide is also declared  in Xaml but this has the same activation limitations as simply specifying the Type. So this is a huge problem for an MVC style application.

What I really wanted to do was to create interfaces for all of my Modelsobjects, such as IProduct and IPurchase. Then I could create some mock objects for my test environment and let the other developer create the real objects for the real application. Well how the heck do you use the ObjectDataProvider so that it’s possible to bind against an abstract Model, the real instance of which is created by the controller? I think the answer is that you cannot, well not without sacrificing design time databinding support at least.

After looking at it for a while I realized that if I set IsInitialLoadEnabled property of my ObjectDataSource to false then after the controller is set in my form I could set the ObjectInstance field to my Model provided by the controller, then call InitialLoad. This would work but no design time support 🙁

You’d think that you could specify the ObjectType for design time support then, using the initial load disabled trick create the real object but you would be wrong. Doing this throws an exception, you cannot set both fields for some inexplicable reason. The next thing you’d think of would be to inherit from ObjectDataProvider, override a method that creates the instance and instead create an event such as LoadInstance so that your controller can pass in the instance instead… but once again you’d be wrong. It seems that the ObjectDataProvider does not really expose any virtual methods of much use.

My next thought is to try to create an MvcDataProvider that supports this functionality a little better. I’m a little hesitant to do this though because of the difficulties I’ve had in the past creating a DataSource for ASP.NET. What a nightmare that was, even a very simple one.

Other than this one problem (which I’m hoping is just an ignorance problem still) I have to say I am enjoying using WPF immensely. Maybe creating a new DataSourceProvider will be just as easy and intuitive as the rest of WPF.

If anybody has any insight on how to resolve this issue I’d love to hear it. If I end up creating an MvcDataProvider I’ll be sure to post it in another blog.

AppDomain TransparentProxy Objects of Different Type

I have a very perplexing situation related to AppDomains. I am trying to create a new AppDomain (so I can load arbitrary assemblies and unload them again) but I am unable to cast returned objects to Types that I am able to use.

Specifically I have an object of Type EntityField[] being returned. If I set it to an object I can see that the Type is correct by calling GetType() in the watch window however whenever I cast it from an object to a strongly typed array I get a null value. Here is a little debugger screen shot.

I believe what is happening is that my assembly is being loaded into both AppDomains. So, while the objects are able to correctly identify themselves as the correct types it seems that the runtime is interpretting them as different types, despite the fact that they’re coming from the exact same Assembly (even the same file path).

What is the solution to this problem?? Should I not be loading the assembly into both domains? It seems to do this automatically when I try to create the proxy instance. One interesting thing to note is that I had to add an event handler for AppDomain.Current.AssemblyResolve, which I then loop through the local assemblies and return the one who’s fullname matches the args.FullName. Is there a more correct way to resolve assemblies? Why is it not resolved automatically, without any help, to begin with?

If anybody knows I’d greatly appreciate some help figuring this out.

As a side note, I’d like to offically vote for the ability to unload assemblies from the current AppDomain. That would be a nice feature.