4

我正在尝试在我的结构映射注册表中的通用工厂类上使用一种方法。通常,在使用工厂方法注册类型时,我会使用以下内容:

For<Foo>().Use(x => new FooFactory().GetFoo());

注册泛型类型时的以下内容:

For(typeof(ISomeGeneric<>)).Use(typeof(SomeGeneric<>));

如何将两者结合起来并从泛型工厂方法中检索泛型类型?我认为它应该是这样的:

For(typeof(IFoo<>)).Use(typeof(x => new FooFactory<>().Create(someParameter));

这只是给出了一个

"Cannot convert lambda expression to type object because it is not a delegate type" 

错误。我尝试了各种组合,但被难住了。有任何想法吗?

谢谢。

4

1 回答 1

0

这是可能的,但如果可以的话,我会寻找替代方案。问题是要使用开放泛型,您必须使用一些反射。这意味着您将受到性能影响。

public class FooRegistry:Registry
{
    public FooRegistry()
    {
        For(typeof(IFoo<>)).Use(x =>
        {
            var ParamType = x.BuildStack.Current.RequestedType
                             .GetGenericArguments()[0];
            return BuildUsingFooFactory(ParamType);
        });
    }

    private object BuildUsingFooFactory(Type paramType)
    {
        var factoryType = typeof (FooFactory<>).MakeGenericType(new[] {paramType});
        var createMethod = factoryType.GetMethod("Create");
        object factory = Activator.CreateInstance(factoryType);
        return createMethod.Invoke(factory, new[] {"SomeParameterString"});
    }
}

public class FooFactory<T>
{
    public IFoo<T> Create(string param)
    {
        return new Foo<T>();
    }

}

public interface IFoo<T>
{
}

public class Foo<T> : IFoo<T>
{   
}

您正在按顺序执行以下操作:

  1. 找出请求的通用参数是什么。(参数类型)
  2. 为工厂创建非开放的泛型类型(factoryType)
  3. 抓住它的 create 方法。(创建方法)
  4. 使用Activator(工厂)创建工厂实例
  5. 使用您的一些参数调用工厂实例上的 create 方法。

StructureMap 负责将输出转换为正确的接口。

更好的解决方案

不要直接使用 IFoo,而是使用 IFooFactory。这使它更干净,你有一个到 IFooFactory<> 的开放通用映射。然后只需获取生成对象所需的 FooFactory 类型。

public class FooRegistry:Registry
{
    public FooRegistry()
    {
        For(typeof (IFooFactory<>))
            .Use(typeof (FooFactory<>))
            .CtorDependency<string>("connection")
            .Is("SomeConnectionString");
    }
}


public interface IFooFactory<T>
{
    IFoo<T> CreateInstance();
}

public class FooFactory<T> : IFooFactory<T>
{
    public FooFactory(string connection)
    {
    } 

    public IFoo<T> CreateInstance()
    {
        return new Foo<T>();
    }
}

public interface IFoo<T>
{
}

public class Foo<T> : IFoo<T>
{   
}
于 2014-03-14T03:34:47.653 回答