1

プロバイダーパターンとUnityを使用しています。

これは典型的なプロバイダーの実装です。私はSomeProvider、抽象メソッドとインスタンス化するロジックを備えた抽象ベースプロバイダーを持っていますdefaultProvider

public abstract class SomeProvider : ProviderBase
{
    #region provider boilerplate

    private const string PROVIDER_NAME = "someProvider";
    private static volatile SomeProvider defaultProvider = null;
    public static SomeProvider Provider
    {
        get { return defaultProvider; }
    }
    private static object providerLockObject = new object();
    static SomeProvider()
    {
        LoadProvider();
    }
    private static void LoadProvider()
    {
        if (defaultProvider == null)
        {
            lock (providerLockObject)
            {
                if (defaultProvider == null)
                {
                    // exception handling omitted for brevity
                    var section = ConfigurationManager.GetSection(PROVIDER_NAME)
                        as BaseProviderConfigurationSection;
                    defaultProvider = ProvidersHelper.InstantiateProvider(
                        section.Providers[section.DefaultProvider], typeof(SomeProvider)) as SomeProvider;
                }
            }
        }
    }

    protected SomeProvider() { }

    #endregion

    #region abstract methods

    public abstract bool DoSomething();

    #endregion
}

これがASomeProviderを実装するものSomeProviderです。依存関係はありますが、そうではないことに注意しASomeProviderてください。ADependencySomeProvider

public class ASomeProvider : SomeProvider
{
    #region provider boilerplate

    private string name;
    public override string Name
    {
        get { return name; }
    }

    public override void Initialize(string name, NameValueCollection config)
    {
        this.name = name;
        base.Initialize(name, config);
    }

    #endregion

    // Provider pattern needs parameterless ctor and calls this
    public ASomeProvider() { }
    // constructor injection
    public ASomeProvider(ADependency aDependency)
    {
        this.ADependency = aDependency;
    }

    [Dependency]
    public SomeDependency ADependency { get; set; }

    #region methods

    public override void DoSomething()
    {
        // do something
    }

    #endregion
}

class SomeDependency {}

私はASomeProvider次のようにビジネスレイヤーでを使用します。

public class SomeBusinessLayer
{
    public SomeProvider someProvider;

    public SomeBusinessLayer(SomeProvider someProvider)
    {
        this.someProvider = someProvider;
    }

    #region methods
    public bool DoSomethingWrapper()
    {
        return someProvider.DoSomething();
    }
    #endregion
}

BusinessLayerFactoryUnityを使用してオブジェクトを配線し、次のようにオブジェクトを返すためのファクトリがあります。

public static class BusinessLayerFactory
{
    private static UnityContainer container;

    private static void WireUp()
    {
        container = new UnityContainer();

        container.RegisterInstance(SomeProvider.Provider);
        container.RegisterInstance(new SomeDependency());
        container.RegisterType<SomeBusinessLayer>(new ContainerControlledLifetimeManager());
    }
    public static SomeBusinessLayer SomeBusinessLayer_Unity
    {
        get
        {
            return container.Resolve<SomeBusinessLayer>();
        }
    }
    public static SomeBusinessLayer SomeBusinessLayer_Self()
    {
        var asomeProvider = SomeProvider.Provider as ASomeProvider;
        if (asomeProvider != null && asomeProvider.ADependency == null)
            asomeProvider.ADependency = new ADependency();
        return new SomeBusinessLayer(SomeProvider.Provider);
    }
}

私が抱えている問題は、を取得するために解決するとSomeBusinessLayer、のsomeProvider依存関係ADependencyがnullになることです。

var someBusinessLayer = BusinessLayerFactory.SomeBusinessLayer_Unity;

((ASomeProvider)someBusinessLayer.someProvider).ADependencyですnull

その理由は、プロバイダーパターンがヘルパーメソッドを使用して、 ProvidersHelper.InstantiateProvider(ProviderSettings providerSettings, Type type)UnityのResolve<T>()メソッドではなくデフォルトプロバイダーをインスタンス化するためです。

SomeBusinessLayer_Self私が新しい ADependency場合に示されているように、Unityなしでこれを行うことを考えることができますが、nullUnityがこれを処理するかどうかとどのように処理するのか疑問に思っています。

メソッドインジェクションまたはCtorインジェクションは私には問題ありません。

これを修正して、UnityとProviderパターンを連携させるにはどうすればよいですか?Unityを使用する主な理由は、工場でオブジェクトを配線することです。

私はMVCを使用していません。

アップデート:

これを修正するには:@seth-flowersへの帽子のヒント

明示的なキャストなしでは方法を見つけることができませんでしたcontainer.BuildUp<ASomeProvider>(aSomeProvider)

container.RegisterInstance(new SomeDependency());

//this does not build up the object with dependency
container.BuildUp(SomeProvider.Provider);
//this works and does build up
var aSomeProvider = SomeProvider.Provider as ASomeProvider;
if(aSomeProvider != null)
    container.BuildUp<ASomeProvider>(aSomeProvider);
//compile error
container.BuildUp<ASomeProvider>(SomeProvider.Provider);

container.RegisterInstance(SomeProvider.Provider);

container.RegisterType<SomeBusinessService>(new ContainerControlledLifetimeManager());
4

1 に答える 1

1

インスタンスの依存関係を具体化するために、メソッドでUnityContainer.BuildUpを使用できませんでしたか? オブジェクトは引き続きプロバイダーの実装を通じて構築されますが、ユニティを通じて依存性注入が行われます。BusinessLayerFactory.WireUpSomeProvider.Provider

例えば:

private static void WireUp()
{
    container = new UnityContainer();

    container.RegisterInstance(SomeProvider.Provider);
    container.RegisterInstance(new SomeDependency());
    container.RegisterType<SomeBusinessLayer>(
        new ContainerControlledLifetimeManager());

    container.BuildUp<ASomeProvider>(SomeProvider.Provider as ASomeProvider);
}

BuildUpのドキュメントには、次のように記載されています。

このメソッドは、インスタンス (たとえば、ASP.NET ページまたは XAML 経由で作成されたオブジェクト) の構築を制御しないが、プロパティやその他の挿入を実行したい場合に役立ちます。

于 2012-10-31T18:01:56.517 に答える