Замок Виндзор регистрация открытых типовых декораторов - PullRequest
2 голосов
/ 22 ноября 2010

Я пытаюсь выяснить, как зарегистрировать декораторы для универсальных типов с 2 универсальными параметрами.Первый тестовый пример ниже - это просто проверка работоспособности для случая с 1 универсальным параметром, который я добавил, когда случай с 2 ​​параметрами не работал должным образом.

Третий (неудачный) случай с 1-универсальным параметром (на этот раз контравариантным), по-видимому, указывает на то, что Виндзор по-разному относится к ко-и контравариантным универсальным параметрам, поэтому мой вопрос: что я здесь делаю неправильно?

Я использую .NET 4.0.

    [Test]
    public void RepoSingleGenericTest()
    {
        var windsorContainer = new Castle.Windsor.WindsorContainer();

        windsorContainer
            .Register(AllTypes.Of(typeof(IRepoSingle<>))
            .FromAssembly(typeof(StringRepoSingle).Assembly)
            .If(t => typeof(CachingRepoSingle<>).IsAssignableFrom(t))
            .WithService.FromInterface(typeof(IRepoSingle<>)));

        windsorContainer
            .Register(AllTypes.Of(typeof(IRepoSingle<>))
            .FromAssembly(typeof(BoolRepoSingle).Assembly)
            .Unless(t => typeof(CachingRepoSingle<>).IsAssignableFrom(t))
            .WithService.FromInterface(typeof(IRepoSingle<>)));

        var stringRepo = windsorContainer.Resolve<IRepoSingle<string>>();
        Assert.IsInstanceOf<StringRepoSingle>(stringRepo);

        var boolRepo = windsorContainer.Resolve<IRepoSingle<bool>>();
        Assert.IsInstanceOf<BoolRepoSingle>(boolRepo);
    }

    [Test]
    public void RepoDoublyGenericTest()
    {
        var windsorContainer = new Castle.Windsor.WindsorContainer();

        windsorContainer
            .Register(AllTypes.Of(typeof(IRepoDoublyGeneric<,>))
            .FromAssembly(typeof(StringRepoDoublyGeneric).Assembly)
            .If(t => typeof(CachingRepoDoublyGeneric<,>).IsAssignableFrom(t))
            .WithService.FromInterface(typeof(IRepoDoublyGeneric<,>)));

        windsorContainer
            .Register(AllTypes.Of(typeof(IRepoDoublyGeneric<,>))
            .FromAssembly(typeof(DateTimeRepoDoublyGeneric).Assembly)
            .Unless(t => typeof(CachingRepoDoublyGeneric<,>).IsAssignableFrom(t))
            .WithService.FromInterface(typeof(IRepoDoublyGeneric<,>)));

        var stringRepo = windsorContainer.Resolve<IRepoDoublyGeneric<Guid, string>>();
        Assert.IsInstanceOf<CachingRepoDoublyGeneric<Guid, string>>(stringRepo);

        var dateTimeRepo = windsorContainer.Resolve<IRepoDoublyGeneric<Guid, DateTime>>();
        Assert.IsInstanceOf<CachingRepoDoublyGeneric<Guid, DateTime>>(dateTimeRepo);
    }

    [Test]
    public void CommandTest()
    {
        var windsorContainer = new Castle.Windsor.WindsorContainer();

        windsorContainer
            .Register(AllTypes.Of(typeof(ICommand<>))
            .FromAssembly(typeof(GuidCommand).Assembly)
            .If(t => typeof(DecoratorCommand<>).IsAssignableFrom(t))
            .WithService.FromInterface(typeof(ICommand<>)));

        windsorContainer
            .Register(AllTypes.Of(typeof(ICommand<>))
            .FromAssembly(typeof(StringCommand).Assembly)
            .Unless(t => typeof(DecoratorCommand<>).IsAssignableFrom(t))
            .WithService.FromInterface(typeof(ICommand<>)));

        var stringComand = windsorContainer.Resolve<ICommand<string>>();
        Assert.IsInstanceOf<DecoratorCommand<string>>(stringComand);

        var guidCommand = windsorContainer.Resolve<ICommand<Guid>>();
        Assert.IsInstanceOf<DecoratorCommand<Guid>>(guidCommand);
    }

    public interface IRepoSingle<out TValue>
    {
        TValue Get();
    }

    public class StringRepoSingle : IRepoSingle<string>
    {
        public string Get()
        {
            throw new NotImplementedException();
        }
    }

    public class BoolRepoSingle : IRepoSingle<bool>
    {
        public bool Get()
        {
            throw new NotImplementedException();
        }
    }

    public class CachingRepoSingle<T> : IRepoSingle<T>
    {
        private readonly IRepoSingle<T> realRepo;

        public CachingRepoSingle(IRepoSingle<T> realRepo)
        {
            if (realRepo == null) throw new ArgumentNullException("realRepo");

            this.realRepo = realRepo;
        }

        public T Get()
        {
            throw new NotImplementedException();
        }
    }

    public interface IRepoDoublyGeneric<in TKey, out TValue>
    {
        TValue Get(TKey key);
    }

    public class StringRepoDoublyGeneric : IRepoDoublyGeneric<Guid, string>
    {
        public string Get(Guid key)
        {
            throw new NotImplementedException();
        }
    }

    public class DateTimeRepoDoublyGeneric : IRepoDoublyGeneric<Guid, DateTime>
    {
        public DateTime Get(Guid key)
        {
            throw new NotImplementedException();
        }
    }

    public class CachingRepoDoublyGeneric<TKey, TValue> : IRepoDoublyGeneric<TKey, TValue>
    {
        private readonly IRepoDoublyGeneric<TKey, TValue> realRepo;

        public CachingRepoDoublyGeneric(IRepoDoublyGeneric<TKey, TValue> realRepo)
        {
            if (realRepo == null) throw new ArgumentNullException("realRepo");

            this.realRepo = realRepo;
        }

        public TValue Get(TKey key)
        {
            throw new NotImplementedException();
        }
    }

    public interface ICommand<in T>
    {
        void Do(T t);
    }

    public class StringCommand : ICommand<string>
    {
        public void Do(string t)
        {
            throw new NotImplementedException();
        }
    }

    public class GuidCommand : ICommand<Guid>
    {
        public void Do(Guid t)
        {
            throw new NotImplementedException();
        }
    }

    public class DecoratorCommand<T> : ICommand<T>
    {
        private readonly ICommand<T> realComamnd;

        public DecoratorCommand(ICommand<T> realComamnd)
        {
            if (realComamnd == null) throw new ArgumentNullException("realComamnd");

            this.realComamnd = realComamnd;
        }

        public void Do(T t)
        {
            throw new NotImplementedException();
        }
    }

ОБНОВЛЕНИЕ: следующее делает свое дело, но я не могу сказать, что думаю, что это самое элегантное решение ...:

        [Test]
    public void RepoDoublyGenericWithReflection()
    {
        var windsorContainer = new Castle.Windsor.WindsorContainer();

        // Register components for a caching decorator for all types implementing IRepoDoublyGeneric<,> - except for the generic cache itself
        (from t in typeof (DateTimeRepoDoublyGeneric).Assembly.GetTypes()
            let iRepo = t.GetInterfaces().SingleOrDefault( i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IRepoDoublyGeneric<,>))
            where
                t.IsClass && !t.IsAbstract && !typeof(CachingRepoDoublyGeneric<,>).IsAssignableFrom(t)
                && iRepo != null
            select iRepo)
         .ForEach(rt => 
             windsorContainer.Register(Component.For(rt).ImplementedBy((typeof(CachingRepoDoublyGeneric<,>)).MakeGenericType(rt.GetGenericArguments()))) 
         );

        // Real repositories
        windsorContainer.Register(
            AllTypes.Of(typeof(IRepoDoublyGeneric<,>))
            .FromAssembly(typeof(DateTimeRepoDoublyGeneric).Assembly)
            .Unless(t => typeof(CachingRepoDoublyGeneric<,>).IsAssignableFrom(t))
            .WithService.FromInterface(typeof(IRepoDoublyGeneric<,>))
        );

        var stringRepo = windsorContainer.Resolve<IRepoDoublyGeneric<Guid, string>>();
        Assert.IsInstanceOf<CachingRepoDoublyGeneric<Guid, string>>(stringRepo);

        var dateTimeRepo = windsorContainer.Resolve<IRepoDoublyGeneric<Guid, DateTime>>();
        Assert.IsInstanceOf<CachingRepoDoublyGeneric<Guid, DateTime>>(dateTimeRepo);
    }

Следуя советам Кшиштофа, я 'Мы также попробовали:

        [Test]
    public void CommandTestUsingBasedOn()
    {
        var windsorContainer = new Castle.Windsor.WindsorContainer();

        windsorContainer
            .Register(AllTypes.Of(typeof(ICommand<>))
            .FromAssembly(typeof(GuidCommand).Assembly)
            .If(t => typeof(DecoratorCommand<>).IsAssignableFrom(t))
            .BasedOn(typeof(ICommand<>))
            .WithService.Base());

        windsorContainer
            .Register(AllTypes.Of(typeof(ICommand<>))
            .FromAssembly(typeof(StringCommand).Assembly)
            .Unless(t => typeof(DecoratorCommand<>).IsAssignableFrom(t))
            .BasedOn(typeof(ICommand<>))
            .WithService.Base());

        var stringComand = windsorContainer.Resolve<ICommand<string>>();
        Assert.IsInstanceOf<DecoratorCommand<string>>(stringComand);

        var guidCommand = windsorContainer.Resolve<ICommand<Guid>>();
        Assert.IsInstanceOf<DecoratorCommand<Guid>>(guidCommand);
    }
  • , но это не меняет поведения.

1 Ответ

4 голосов
/ 23 ноября 2010

Работает ли оно, когда вы регистрируете его как AllTypes.BasedOn(typeof(typeof(ICommand<>)) и WithService.Base()?

...