views:

77

answers:

2

I'm just wondering if there is a DI Framework for .net that handles string-to-some type conversion for me?

Basically I have this constructor:

public MyImplTwo(bool someParam)

and a string like "true" or "1". I've tried Unity, but this throws an error saying that no constructor with the signature MyImplTwo(string) exists:

container.RegisterType<MyImplBase, MyImplTwo>(new InjectionConstructor(new object[] {"true"}));

Is there one? Essentially I mainly need a wrapper around Activator.CreateInstance, so I'm looking for the simplest IoC that works. On the other hand, I wouldn't mind the extra functionality of the "big" containers as long as the above works.

Edit: I can get the desired type as a string as well, and if required also the argumentName. The things I cannot do is a) have a container-specific config file (configuration is done through a database) and b) decorate the classes that should be resolved with any attributes as I don't control them.

+1  A: 

As far as I am aware, System.Boolean does not have a constructor that will allow it to be instantiated with Activator.CreateInstance. You'll probably have to use Boolean.Parse() or Boolean.TryParse().

I don't know of any IO frameworks that do what you want, but could you perhaps just work with your preferred framework, like so... (using Autofac, for example):

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<MyImplTwo>()
    .As<MyImplBase>()
    .WithParameter("someParam", Boolean.Parse(yourStringHere));

or, for types that you can instantiate with Activator.CreateInstance:

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<MyImplTwo>()
    .As<MyImplBase>()
    .WithParameter("someOtherParam", Activator.CreateInstance(Type.GetType("TypeName"), new object[] { }));

Edit: Another option would be to extend a DI framework of your choosing, and combine it with some string serialization functionality.

For example, using Autofac with Json.NET, we can create the extension method:

static class AutofacExtensions
{
    public static IRegistrationBuilder<TLimit, TReflectionActivatorData, TStyle>
        WithSerializedParameter<TLimit, TReflectionActivatorData, TStyle>(
            this IRegistrationBuilder<TLimit, TReflectionActivatorData, TStyle> registration, 
            string parameterName, 
            string typeName, 
            string value) 
        where TReflectionActivatorData : ReflectionActivatorData
    {
        return registration.WithParameter(parameterName, JsonConvert.DeserializeObject(value, Type.GetType(typeName)));
    }
}

And use the extension method as follows:

ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<MyImplTwo>()
    .As<MyImplBase>()
    .WithSerializedParameter("someParam", "System.Boolean", "true");
Joviee
+1  A: 

Based on the edit in your question, I'd say Castle Windsor should be able to address your needs.

Using Windsor's XML configuration, you can specify primitive parameter values, e.g.

<component id="myImp"
           service="MyImplBase, MyAssembly"
           type="MyImplTwo, MyOtherAssembly">
    <parameters>
        <someParam>true</someParam>
    </parameters>
</component>

Windsor doesn't require you to put the XML configuration in an application configuration file. You can read it from any XML stream, including from a database. Here's a code snippet that shows how to read XML configuration from an XML string:

string myXml = // read XML from a custom resource...

var container = new WindsorContainer();
container.Install(
    new ConfigurationInstaller(
        new XmlInterpreter(
            new StaticContentResource(myXml))));

You can now use container to resolve MyImplBase and it will return an instance of MyImplTwo with someParam set to true.

Also with Windsor you can pass dependencies as strings to the fluent registration API, and conversion subsystem in Windsor will convert them for you, which completely eliminates need for any form of XML config.

Mark Seemann
more precisely Windsor has a conversion subsystem that implements `ITypeConverter` that does all this stuff
Krzysztof Koźmic