Разрешающая реализация «Супер интерфейса» в Виндзорском замке - PullRequest
1 голос
/ 05 ноября 2019

Может быть, даже невозможно, но здесь мне нужно.
У меня есть общая реализация средства отображения ключей и класс Factory, способный генерировать такие средства отображения

public class KeyMapperFactory 
{
    IKeyMapper<TInternalKey, TExternalKey> GetMapper<TInternalKey, TExternalKey>(MapperConfig config)
}

Теперь я хотел бы иметь интерфейсыэто "говорить ясно" в приложении, поэтому я бы создал еще один пустой интерфейс в моем приложении, как это

public interface IMapCompanyToPayrollCompany : IKeyMapper<CompanyId, PayrollCompanyId>
{
}

Есть ли у меня шансы создать реализацию "на лету" IMapCompanyToPayrollCompany с использованием CastleWindsor вчто-то вроде этого (неправильного) пути?

var mapperConfig = MapperConfig {
...
};
var keyMapperFactory = new KeyMapperFactory();
var container = new WindsorContainer();

container.Register(
    Component
        .For<IMapCompanyToPayrollCompany>()
        .UsingFactoryMethod(kernel => (IMapCompanyToPayrollCompany)keyMapperFactory.GetMapper<CompanyId, PayrollCompanyId>(mapperConfig)
);

1 Ответ

2 голосов
/ 06 ноября 2019

Я нашел решение с помощью Castle's DynamicProxies

// I developed an extension method on the IWindsorContainer
public static void RegisterMapper<TSpeakingInterface, TInternal, TExternal>(this IWindsorContainer container, MapperConfig config) 
    where TSpeakingInterface : IKeyMapper<TInternal, TExternal>
{
    container.Register(
        Component
            .For<IMapCompanyToPayrollCompany>()
            .UsingFactoryMethod(() => {
                var generator = new ProxyGenerator(); // <--Documentation recommend this to be a Singleton for performance and memory reason ... 
                var keyMapperFactory = new KeyMapperFactory();
                var mapper = keyMapperFactory.GetMapper<TInternal, TExternal>(config);
                var interceptor = new KeyMapperInterceptor<TInternal, TExternal>(mapper);

                // see: https://github.com/castleproject/Windsor/issues/224
                var nullProxy = generator.CreateInterfaceProxyWithoutTarget<TSpeakingInterface>();
                return generator.CreateInterfaceProxyWithTarget(nullProxy, interceptor);
            })
    );
}

// Now I can register a mapper this way:
var container = new WindsorContainer();
var config = new MapperConfig {
    [...] // mapper config stuff here
}
container.RegisterMapper<IMapCompanyToPayrollCompany, CompanyId, PayrollCompanyId>(config);

Перехватчик прост как этот

public class KeyMapperInterceptor<TInternal, TExternal> : IInterceptor
{
   private readonly IKeyMapper<TInternal, TExternal> realMapper;

   public KeyMapperInterceptor(IKeyMapper<TInternal, TExternal> realMapper)
   {
       this.realMapper = realMapper;
   }

    public void Intercept(IInvocation invocation)
    {
       // We simply call the corresponding method on the realMapper
       var method = invocation.Method;
       invocation.ReturnValue = method.Invoke(realMapper, invocation.Arguments);
    }
}

... и он работает! Конечно, дополнительные методы или свойства не разрешены в IMapCompanyToPayrollCompany, потому что перехватчик попытается выполнить / получить доступ к ним на «realMapper», который ничего не знает о!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...