2

Autofac を Catel のプライマリ コンテナーとして使用する方法はありますか? Unity、Ninject、MEF、Windsor、および Unity がサポートされていることを見てきましたが、Autofac 統合については言及されていません。

4

2 に答える 2

3

Autofac のヘルパーは作成していませんし、作成する予定もありません。

次のオプションがあります。

1) Helper クラスを自分で作成し (他の例を参照)、登録すると、ServiceLocator で同期できます。

2) Catel の最新のプレリリース (3.7 プレリリース) では、IDependencyResolver を導入しました。このインターフェイスを Autofac コンテナーに実装し、それを ServiceLocator に登録できます。ただし、これは完全にはサポートされていないため、副作用が発生する可能性があることに注意してください。

3) Catel で ServiceLocator を使用する

2013-09-14 に編集

4) Catel の最新バージョン (ナイトリー ビルド) に関心がある場合は、デフォルトのサービス ロケーターを実装に置き換えることができます。

問題の詳細: https://catelproject.atlassian.net/browse/CTL-175

ドキュメント: https://catelproject.atlassian.net/wiki/pages/viewpage.action?pageId=622682#IoC(ServiceLocatorandTypeFactory)-Replaceingthedefaultcomponents

于 2013-09-11T15:26:41.450 に答える
1

これが Catel 3.8 と Autofac の私のソリューションです (他のサードパーティのコンテナーでも動作するはずです)。
私はIDependencyResolver、Autofac コンテナーに裏打ちされた の実装と の実装を作成しましたIServiceLocator。前者には、アプリケーションのサードパーティ IoC 構成とロジックが含まれています。後者は、Catels モジュールのすべての型とインスタンスの登録を取得し、それらを Autofac に転送するために使用されます。

基本戦略は、

  1. サードパーティ コンテナを作成して構成する
  2. これを使用して (部分的にカスタマイズされた) Catel IoC コンポーネントをインスタンス化し、それらを Catels IoC 構成に導入します
  3. 以前に作成された (カスタマイズされた) 実装を使用して Catel に型とインスタンスの登録を行わせ、それらをサード パーティのコンテナーに転送します。

だからここに私の実装がありIServiceLocatorます:

internal class CustomServiceLocator : IServiceLocator
    {
        private readonly CustomDependencyResolver _dependencyResolver;

        public CustomServiceLocator(CustomDependencyResolver dependencyResolver)
        {
            _dependencyResolver = dependencyResolver;
        }

        public object GetService(Type serviceType)
        {
            throw new NotImplementedException();
        }

        public RegistrationInfo GetRegistrationInfo(Type serviceType, object tag = null)
        {
            throw new NotImplementedException();
        }

        public bool IsTypeRegistered(Type serviceType, object tag = null)
        {
            return _dependencyResolver.CanResolve(serviceType, tag);
        }

        public bool IsTypeRegisteredAsSingleton(Type serviceType, object tag = null)
        {
            throw new NotImplementedException();
        }

        public void RegisterInstance(Type serviceType, object instance, object tag = null)
        {
            var builder = new ContainerBuilder();
            IRegistrationBuilder<object, SimpleActivatorData, SingleRegistrationStyle> registrationBuilder = builder.RegisterInstance(instance);

            if (tag != null)
            {
                registrationBuilder.Keyed(tag, serviceType);
            }

            _dependencyResolver.UpdateContainer(builder);
        }

        public void RegisterType(Type serviceType, Type serviceImplementationType, object tag = null, RegistrationType registrationType = RegistrationType.Singleton,
            bool registerIfAlreadyRegistered = true)
        {
            var builder = new ContainerBuilder();
            IRegistrationBuilder<object, ConcreteReflectionActivatorData, SingleRegistrationStyle> registrationBuilder = builder.RegisterType(serviceImplementationType).As(serviceType);

            if (tag != null)
            {
                registrationBuilder.Keyed(tag, serviceType);
            }

            switch (registrationType)
            {
                case RegistrationType.Singleton:
                    registrationBuilder.SingleInstance();
                    break;
                case RegistrationType.Transient:
                    registrationBuilder.InstancePerDependency();
                    break;
                default:
                    registrationBuilder.InstancePerDependency();
                    break;
            }

            _dependencyResolver.UpdateContainer(builder);
            TypeRegistered(this, new TypeRegisteredEventArgs(serviceType, serviceImplementationType, tag, registrationType));
        }

        public object ResolveType(Type serviceType, object tag = null)
        {
            // Must be implemented. Catels ViewModelBase resolves the DependencyResolver in ctor using the ServiceLocator...Why???
            return _dependencyResolver.Resolve(serviceType, tag);
        }

        public IEnumerable<object> ResolveTypes(Type serviceType)
        {
            throw new NotImplementedException();
        }

        public void RemoveInstance(Type serviceType, object tag = null)
        {
            throw new NotImplementedException();
        }

        public void RemoveAllInstances(Type serviceType)
        {
            throw new NotImplementedException();
        }

        public void RemoveAllInstances(object tag = null)
        {
            throw new NotImplementedException();
        }

        public bool IsExternalContainerSupported(object externalContainer)
        {
            throw new NotImplementedException();
        }

        public void RegisterExternalContainer(object externalContainer)
        {
            throw new NotImplementedException();
        }

        public void RegisterExternalContainerHelper(IExternalContainerHelper externalContainerHelper)
        {
            throw new NotImplementedException();
        }

        public void ExportInstancesToExternalContainers()
        {
            throw new NotImplementedException();
        }

        public void ExportToExternalContainers()
        {
            throw new NotImplementedException();
        }

        public bool AreAllTypesRegistered(params Type[] types)
        {
            return _dependencyResolver.CanResolveAll(types);
        }

        public object[] ResolveAllTypes(params Type[] types)
        {
            return _dependencyResolver.ResolveAll(types);
        }

        public bool AutomaticallyKeepContainersSynchronized { get; set; }
        public bool CanResolveNonAbstractTypesWithoutRegistration { get; set; }
        public bool SupportDependencyInjection { get; set; }
        public bool AutoRegisterTypesViaAttributes { get; set; }
        public bool IgnoreRuntimeIncorrectUsageOfRegisterAttribute { get; set; }
        public event EventHandler<MissingTypeEventArgs> MissingType;
        public event EventHandler<TypeRegisteredEventArgs> TypeRegistered;
    }

そして、ここに の実装がありIDepencyResolverます。

internal class CustomDependencyResolver : IDependencyResolver
    {
        private readonly IContainer _container;

        public CustomDependencyResolver()
        {
            var builder = new ContainerBuilder();
            builder.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies());
            builder.RegisterInstance(this).SingleInstance(); // dependency of CustomServiceLocator
            builder.RegisterInstance(this).As<IDependencyResolver>().SingleInstance(); // Dependency of ViewModelBase. Catels ViewModelBase resolves the DependencyResolver in ctor using the ServiceLocator...Why???
            builder.RegisterType<CustomServiceLocator>().As<IServiceLocator>().SingleInstance(); // dependency of TypeFactory (subscribes to TypeRegistered event to clear its cache)
            builder.RegisterType<TypeFactory>().As<ITypeFactory>().SingleInstance(); // dependency of ViewModelFactory

            _container = builder.Build();
        }

        public bool CanResolve(Type type, object tag = null)
        {
            return _container.IsRegistered(type);
        }

        public bool CanResolveAll(Type[] types)
        {
            return types.All(type => _container.IsRegistered(type));
        }

        public object Resolve(Type type, object tag = null)
        {
            object obj;
            if (tag == null)
            {
                if (_container.TryResolve(type, out obj))
                    return obj;
            }
            else
            {
                if (_container.TryResolveKeyed(tag, type, out obj))
                    return obj;
            }

            throw new Exception(string.Format("Could not locate any instances of contract {0}.", tag ?? type.Name));
        }

        public object[] ResolveAll(Type[] types, object tag = null)
        {
            var objects = new ArrayList();

            if (tag == null)
            {
                foreach (Type type in types)
                {
                    object obj;
                    if (_container.TryResolve(type, out obj))
                    {
                        objects.Add(obj);
                    }
                    else
                    {
                        throw new Exception(string.Format("Could not locate any instances of contract {0}.", type.Name));
                    }
                }
            }
            else
            {
                foreach (Type type in types)
                {
                    object obj;
                    if (_container.TryResolveKeyed(tag, type, out obj))
                    {
                        objects.Add(obj);
                    }
                    else
                    {
                        throw new Exception(string.Format("Could not locate any instances of contract {0}.", tag));
                    }
                }
            }

            return objects.ToArray();
        }

        public void UpdateContainer(ContainerBuilder builder)
        {
            builder.Update(_container);
        }
    }

起動時にすべてをまとめる:

    public partial class App : Application
    {
        /// <summary>
        /// Raises the <see cref="E:System.Windows.Application.Startup"/> event.
        /// </summary>
        /// <param name="e">A <see cref="T:System.Windows.StartupEventArgs"/> that contains the event data.</param>
        protected override void OnStartup(StartupEventArgs e)
        {
#if DEBUG
            Catel.Logging.LogManager.AddDebugListener();
#endif

            StyleHelper.CreateStyleForwardersForDefaultStyles();

            // create the DependencyResolver and do Catel IoC configuration
            CustomDependencyResolver dependencyResolver = new CustomDependencyResolver();
            DependencyResolverManager.Default.DefaultDependencyResolver = dependencyResolver;
            IoCConfiguration.DefaultDependencyResolver = dependencyResolver;
            IoCConfiguration.DefaultServiceLocator = dependencyResolver.Resolve<IServiceLocator>();
            IoCConfiguration.DefaultTypeFactory = dependencyResolver.Resolve<ITypeFactory>();

            // let Catel register its dependencies
            Catel.Core.ModuleInitializer.Initialize();
            Catel.MVVM.ModuleInitializer.Initialize();

            base.OnStartup(e);
        }
    }

トレードオフと副作用:私の意見では、Catels の IoC 実装は少しあいまいです。たとえば、ServiceLocatorを解決するために が使用されるDependencyResolverこともあれば、その逆の場合もあります。内部で使用される最も一般的な方法を見つけ出し、それらを解決策でカバーしようとしました。アプリケーションの起動後にタイプがAutofacsコンテナに登録され、TypeFactoryそのキャッシュをクリアするように通知されない場合、副作用が発生する可能性があります(私はそれ自体を分析しませんでしたTypeFactory)。に転送するためにCustomDependencyResolverによってサブスクライブされた の TypeRegistered イベントの実装を提案します。CustomServiceLocatorTypeFactory

于 2013-12-08T20:13:02.830 に答える