2015-01-09

Quick reminder about AttachedProperties and AttachedBehaviors

Yet again, I produced too much text than I intended for a short response on StackOverflow.. If somebody is interested in, the question came from StackOverflow: Dynamic Conditional Formatting in WPF.


Let's start with WPF support for "Attached properties". You can literally attach them to anything you like. A Grid.Row is example of such attached property.

Once you create a couple of your att.props, you observe and bind them, and also bind to them as normal:

<Foo x:Name="foo" myns:MyExtension.MyAttachedProperty1="SomeSource.AProperty" />
<Bar myns:MyExtension.MyAttachedProperty2="{Binding Path=(myns:MyExtension.MyAttachedProperty1).Width, ElementName=foo }" />

note that when binding to an attached property, you must use parenthesis in the property path, or else the MyExtension class name will be treated as a source instead of as a classname-prefix. You may also need namespace prefixes (xmlns:my=... + my: everywhere)

Once you learn/master attached properties, things start to be fun! Since you can attach them and bind on almost anything, you can introduce smart extensions like:

<TextBlock m:MyEx.UnitSystem="{Binding ..}" m:MyEx.SourceValue="{Binding ..}" />

Note that TextBlock.Text is not bound. The idea behind it is that SourceValue attached property gets the raw value to be displayed, and its change handlers observe the changes to both DisplayedValue and UnitSystem, and they translate the values and set the Text on the component. Not much suprising.

But the suprising fact that is easily omitted is, that your code will be totally decoupled. You will have a source-of-value, source-of-unitsystem, both just pulled from datasource. Your calculations will just emit the value. And yet another class/file will define the plugin that handles the conversions and updates the TextBlock.

But, ok, so we have the source-value bindings attached like above. Where to put the actual code that handles the changes? Of course, you can put that right into these attached dependency properties, just attach uimetadata with a change-handler and done. Since every change-handler receives the originating DependencyObject=TextBlock, those change handlers will be able to update the Text.

But it'll get really messy once you need to observe two, three or more source properties, because every one of those will need to be really carefully tracked.

So, here's what I like to do in such cases:

<TextBlock my:MyEx.UnitSystem="{Binding ..}"
           my:MyEx.SourceValue="{Binding ..}"
           Text="{Binding (my:MyEx.DisplayedValue), RelativeSource={RelativeSource Self}}">
    <my:AutoUnitConversion />
</TextBlock>

The AutoUnitConversion is an AttachedBehavior that after attaching to TextBox observes changes to UnitSystem and SourceValue and calculates the displayed value. The behavior could directly set the Text of the TextBlock, but then, it would be usable only with TextBlocks. So, instead, I'd make it emit the calculated value as a third property, DisplayedValue. Note the usage of RelativeSource=self, since the output attached property is set right on the parent component. In this setup, you may then directly reuse the AttachedBehavior in other places - just the final Text/Value/etc binding will change.

I think you see now how powerful it can be. It's more complex than styles, bindings and triggers, but on the other hand it allows you to literally attach any logic and any behavior. While bindings and conditions give you some sort of a language to set the rules, it's sometimes simply not enough, or sometimes it actually gets overcomplicated in XAML and writing the same logic by C# or VB is much simpler than via multibindings, converters and conditions. In such case, Behaviors are great!

..but this hint would not be complete without mentioning that Behaviors are really more complex, as you often need to set up or observe some bindings from the Code, not XAML, and also you need to remember about Attach/Detach lifecycle, and also they put some additional overhead to whole system as they introduce more properties/values to be tracked by WPF. It's really hard to tell if it overhead is higher or lower than MultiBindings and lots of Converters. I'd guess it's actually lower, but I have not measured that.

By the way, I almost forgot to add the link: here's a very quick overview about AttachedBehaviors. Please note that this term is used for two things: 'quick&dirty' behaviors registerd through setting a AttachedDependencyProperty, and 'fully-fledged' behaviors registered by XAML tags ("Blend Behaviors", named after MS ExpressionBlend). They look a bit different, but the idea of operation is mostly the same. While creating and using the latter ones is a bit more involving, they tend to be structured better, easier&more reusable than the former, and they come with handy Attach/Detach methods. It's good to familiarize yourself with both types!

2015-01-08

Random findings about EF and the way it sets up Connections and Contexts

Here's the long nontrimmed version of my answer, with all the babbling. If somebody is interested in, the question came from StackOverflow: Dynamic Connection String in Entity Framework.


Ok, as I have not found any trace of the code I produced back then, I started digging again, trying to remember what I tried doing. I remember that finally everything almost worked but I got stuck at ... not being able to provide nor build an instance of EntityConnection because its connection string required three mapping files and as I used Code-First I simply didn't have them. However, in your case it should do the trick.

So.. the most important thing is of course the InternalContext. It's the brain here and it can be initialized in many ways, drived by various DbContext constructors. I first targetted the "ObjectContext" overload and tried to provide my own already-connected instance, but that proved impossible as I finally managed to get hold on a service that returns a provider that returns a factory that builds ObjectContexts ... but this factory required me to pass a DbContext. Remember that I wanted to have ObjCtx to be able to create call DbCtx ctor's overload.. Zonk.

I decompiled the factory and yet again it turned out that current implementation of DbCtx/ObjCtx and this factory that the only point where you can actually callable is inside the DbContext's constructors. The ObjectContext produced by the factory gets bound to that specific DbCtx and it's not possible to untangle them later. I remember that it's all about Connections and Metadata. It was something like "DbCtx provides connection", "DbCtx delegates all other jobs to ObjCtx", "ObjCtx provides metadata" but "ObjCtx does not know where to get metadata from", so it asks a 'service' to find it, which in turn looks up for the connection, which it gets from DbCtx..

There was also some play with IObjectContextAdapter, but I don't remember it now, except for the fact that I got to a point where I rolled in my own ObjectContext2 class (I think I just subclassed the ObjectContext) which provided everything all by itself and didn't need that factory, but I got stuck at not being able to manually construct and initialize Metadata(Workspace?) properly.

So, that was the end of "EagerInternalConnection" path, which was the most promising one, since it did not rely on any defaults and just took everything I provided to it.


The last thing left was InitializeLazyInternalContext (you mentioned), which basically initializes everything according to defaults. That's either the true defaults related to the name of the context class, or you can provide a "nameOrConnectionString" (which I could not use since it expects EntityConnectionString and I used Code-First). Or, there's third option that takes DbCompiledModel. It's protected but when you inherit from DbContext you can call it easily.

It's a bit tricky to get an instance of DbCompiledModel though. It can't be built directly, it has to be obtained from DbModelBuilder, which in turn is often only temporarily available during your XYZContext initialization. Surely you remember OnModelCreating(DbModelBuilder) method where all model configurations take place. So.. but it's inside XYZContext and you need the CompiledModel before you start construction your XYZContext/DbContext again. You can refactor all the model-setup out of the context, or you may simply hack in and expose the protected OnModelCreating method even statically to be able to build models manually. However, there are few bits missing in the OnModelCreating method. There are some base policies and conventions that are set before this method is called, so if you'll be creating them manually.. you'd need to again decompile&find the part that sets them, and I remember it's well private/hidden so you'd need to invoke it via reflection or copy all the setup the code..

Anyways, after refactoring some code I managed to have the DbModelBuilder configured, model build, compiled, passed to new MyDbModel constructor -- and it gridnded to halt again, because of some issues I dont recall now, Sorry..


The factories/services I talked about. It's all around IDbDependencyResolver interface. Look at System.Data.Entity.Infrastructure.DependencyResolution. You'll find it inside. There's handy implementation of a service/instace resolver called SingletonDependencyResolver<T> that will be sufficient in most cases.

Registering resolvers is tricky. If I remember well, I injected the resolvers through (same namespace)DbConfigurationManager.(static)Instance.GetConfiguration() which returns the IoC configuration object and .AddDependencyResolver(..) or .RegisterSingleton<TService>. All internal though, so must use reflection here. I remember that the IoC and resolvers can also be configured with special entries in app.config settings, but I didn't use it as I was focused at 100% runtime configuration. Now I see that actually I didn't need that, when I wanted to inject the resolvers I could certainly do that from appconfig, as the resolver classes would not change in the runtime. You may try so instead of reflection.

Ok, so the resovlers.. There are a bunch of them you can override. I remember playing with ProviderFactoryResolver, InvariantNameResolver, and ProviderServiceResolver. The first one is meant to provide DbProviderFactory that is the root of all connection builders. The second one extracts 'invariant name' from the factory - that's in fact the "dialect" name like "sql2008". Many things are keyed/identified by this "invariant name". I don't remember much about the third ProviderServiceResolver one.

Look first at DbProviderFactoryResolver. If you register your own resolver if this type, you will be able to inject your own DbProviderFactory-ies. Your own DbProviderFactory seems crucial. Look at decompiled EntityConnection and its ChangeConnection method. It is one of the core methods that, well, sets or changes the connection string.

private void ChangeConnection(string ..blah..) {
    ...
    DbProviderFactory fac = null;
    ...
    fac = DbDependencyResolverExtensions.GetService<DbProviderFactory> ( ... )
    ...
    connection = EntityConnection.GetStoreConnection(fac);
    ...
    connstr = ..blah..["provider connection string"];
    DbInterception.Dispatch.Connection.SetConnection(connection, new DbConnectionPropertyInterceptionContext<string>(..).WithValue(connstr) );
}

Yep, the DbProviderFactory you see there is just it. Its CreateConnection returns a DbConnection (it can be yours) and then it configured with 'provider connection string' right from the settings from the entityconnectionstring section. So, if you additionally roll in your own DbConnection, build by your own DbProviderFactory, it could then ignore the incoming connstring in favor of whatever you want.

Also, I have not investigated the DbInterception.Dispatch.Connection.SetConnection part because back then my play-time has run out. There is some slight chance that Interception is mean literally and that you will be able to "just register" an interceptor that will override the "SetConnectionString".


But, well.. that's enormous amount of work. Really. Using separate file to exploit partial to expose additional base DbContext constructor and then inheriting from the autogenerated context class and providing the connstring through that is much much simpler!