从泛型工厂中选择正确的组件

本文关键字:组件 选择 泛型 工厂 | 更新日期: 2023-09-27 18:12:32

解决方案

见@samy的答案,但是开放类是不正确的。我只需要修改:

  StockDelayModule<T> : ModulePartBase<T>, IModulePart<T> where T : StockDelay

  StockDelayModule : ModulePartBase<StockDelay>, IModulePart<StockDelay>

StockDelayModule中对T的所有引用都指向StockDelay

AsFactory()注册然后工作良好,可以解决正确的组件。


我一直不愿意发布这个问题,因为我想弄清楚它,但我也不想看到一连串的"重复"评论,但我很困惑。

我有一个接口

public interface IModulePart<T>
{
    IResponse<T> Create(CreateRequest request, IPromise<T> promise);
    IResponse Delete(DeleteRequest request, IPromise<T> promise);
    IResponse<T> Read(ReadRequest request, IPromise<T> promise);
    IResponse<T> Update(UpdateRequest request, IPromise<T> promise);
}

具有基于T的不同实现。例如:

WebUrlModule<T> : IModulePart<T> where T : WebUrl
StockDelayModule<T> : IModulePart<T> where T : StockDelay

我已经有了我的安装程序,它正在注册组件:

 Classes.FromAssemblyInDirectory(new AssemblyFilter("bin"))
                .BasedOn(typeof(IModulePart<>))                   
                .WithService.Base()
                .LifestyleTransient()

我有我的工厂:

public interface IModulePartFactory
{
    IModulePart<T> FindModulePartFor<T>(); 
}

然后我的工厂选择器正在运行,从DefaultTypedFactoryComponentSelector重写GetComponentType:

protected override Type GetComponentType(MethodInfo method, object[] arguments)
{
    if (method.Name == "FindModulePartFor")
    {
         return typeof(IModulePart<>).MakeGenericType(method.GetGenericArguments()[0]);
    }
    return base.GetComponentType(method, arguments);
}

似乎所有的看起来都是正确的,当调试(使用WebUrl)时,泛型类型类似于IModulePart'1[[WebUrl, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]

然而,正如你可能已经猜到的那样,它不起作用。如果我使用StockDelay进行调用,它会解决得很好,因为我认为它返回了第一个注册的组件,但是当使用WebUrl时,它会中断。我说StockDelay工作,但我认为这更只是情况下,它返回任何东西(第一个匹配组件),而不是选择正确的组件。

我得到的消息是:Types WebUrl don't satisfy generic constraints of implementation type StockDelayModule'1 of component 'StockDelayModule'1'. This is most likely a bug in your code.

任何对任何人来说都很明显的东西,或者对任何可能不正确的东西的建议?或者我只是在尝试一些不可能的事情!?谢谢。


更新

如果我改变我的类抽象和实现他们与派生类,不是泛型它的工作。所以这让我认为这只是一个小的配置在城堡相关的通用,这意味着它没有正确地解决。想法吗?:

public class StockDelayModule : StockDelayModulePart<StockDelay> { }
public abstract class StockDelayModulePart<T> : ModulePartBase<T>, IModulePart<T> { }

从泛型工厂中选择正确的组件

您不需要自定义解析器,因为Castle将尝试根据返回类型解析工厂调用。除非您需要其他一些东西,否则根据T,以下内容应该足以解决IModulePart<T>:

public class WebUrl { }
public class StockDelay { }
public interface IModulePart<T> { }
public class WebUrlModule : IModulePart<WebUrl> { }
public class StockDelayModule : IModulePart<StockDelay> { }
public interface IModulePartFactory
{
    IModulePart<T> FindModulePartFor<T>();
}
internal class Program
{
    private static void Main(string[] args)
    {
        var container = new Castle.Windsor.WindsorContainer();
        container.AddFacility<TypedFactoryFacility>();
        container.Register(
            Classes.FromAssemblyInThisApplication()
                .BasedOn(typeof(IModulePart<>))
                .WithService.Base()
                .LifestyleTransient(),
            Component.For<IModulePartFactory>().AsFactory()
        );
        var factory = container.Resolve<IModulePartFactory>();
        var moduleForWebUrl = factory.FindModulePartFor<WebUrl>(); 
        // type is WebUrlModule
        var moduleForStockDelay = factory.FindModulePartFor<StockDelay>();
        // type is StockDelayModule
    }
}

如果尝试重写其他方法会发生什么:

protected override string GetComponentName(MethodInfo方法,object[] arguments)

集装箱注册说明?您可以检查注册和错误配置组件的部分。

虽然重写此方法可能部分解决问题,但不能解决问题的根源-这是检查您是否错误配置组件的另一种方法。