I have some service behaviors for WCF services that I just want to register; there's no configuration. I figured I could skip creating a BehaviorExtensionElement descendant each time by using generics:
public class SimpleBehaviorExtensionElement<TBehavior> : BehaviorExtensionElement
where TBehavior: new()
{
protected override object CreateBehavior()
{
return new TBehavior();
}
public override Type BehaviorType
{
get { return typeof(TBehavior); }
}
}
And in Web.config:
<behaviorExtensions>
<add name="myBehavior2"
type="WcfService1.SimpleBehaviorExtensionElement`1[[WcfService1.MyBehavior,
WcfService1]], WcfService1"/>
</behaviorExtensions>
WcfService1.MyBehavior exists, implements IServiceBehavior, and has been tested.
But when I reference <myBehavior2/> in the behavior section of the config file, I get:
An error occurred creating the configuration section handler for system.serviceModel/behaviors: Extension element 'myBehavior2' cannot be added to this element. Verify that the extension is registered in the extension collection at system.serviceModel/extensions/behaviorExtensions. Parameter name: element
Everything works if I create a non-generic BehaviorExtensionElement descendant, which I can do. But now it bugs me. ;)
Unfortunately this is not possible with config files, at least not in a reliable fashion.
The reason is that if you have a generic class class A<T>
and a class parameter class B
the framework will not create a the class A<B>
until you declare a type of A<B>
by using it. The name in the format A`1[[B, Assm]] is just the name that gets created at run time - it means the generic "A" that takes 1 parameter created with the following types. It is not a cue to a type factory - which is what you need for what you are doing. So you might be able to get this to work if you are lucky and A<B>
happens to have been declared, but I would not rely on it.
This is, I believe, fixed in the data contract serialization that is used by later parts of the framework, but config is old. If you look at XAML there is the ability to use a type arguments with a type:
<scg3:Dictionary x:TypeArguments="x:String, x:Object">
Note this is an Explicit instruction to a type factory - something that the config parser does not have.
So sadly this leaves you with the expense of declaring a concrete type for each extension - but it is not a lot of work :
public class MyBehaviorExtensionElement :
SimpleBehaviorExtensionElement<MyBehavior> {}
And on the plus side it makes your config file more readable.
<behaviorExtensions>
<add name="myBehavior"
type="BehaviorTest.MyBehaviorExtensionElement, ServiceLibrary"/>
</behaviorExtensions>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With