0

サービスがシングルトンまたは一時的である必要があるかどうかを示す2つのインターフェースがあります。

public interface ITransient {}
public interface ISingleton {}

このインターフェイスを他のインターフェイスとクラスに実装します。

public interface ISession : ISingleton
{
    int? UserId {get;set;}
}

public class Session : ISession
{
    public int? UserId {get;set;}
}

次に、他のサービスにセッションを挿入します。

public interface IBookService : ITransient
{
    ...
}

public class BookService : IBookService
{
    public BookService(ISession session) { ... }
    ...
}

ISingleton を実装する型のすべてのインスタンス リクエストを Singleton ライフサイクルで作成する必要があるように StructureMap を構成する方法は??

私はそれを試しました:

Container.Configure(conf => {
    conf.For<ITransient>().Transient();
    conf.For<ISingleton>().Singleton();
}

しかし、何も...動作しません。SessionオブジェクトをTransientとして作成してください。

私も試してみました:

        Container.Configure(conf =>
        {
            conf.Scan(s =>
            {
                s.Assembly(assembly);
                s.LookForRegistries();

                s.AddAllTypesOf<ISingletonDependency>();
                s.AddAllTypesOf<ITransientDependency>();
            });

            conf.For<ITransientDependency>().Transient();
            conf.For<ISingletonDependency>().Singleton();
        });

そして何も...

ウィンザー城を使用してそれを行う方法を見てきました:

        context.IocContainer.Register(
            Classes.FromAssembly(context.Assembly)
                .IncludeNonPublicTypes()
                .BasedOn<ITransient>()
                .WithService.Self()
                .WithService.DefaultInterfaces()
                .LifestyleTransient()
        );

        //Singleton
        context.IocContainer.Register(
            Classes.FromAssembly(context.Assembly)
                .IncludeNonPublicTypes()
                .BasedOn<ISingleton>()
                .WithService.Self()
                .WithService.DefaultInterfaces()
                .LifestyleSingleton()

しかし、StructureMap を使用する方法がわかりません...

他の可能性は、規則 (IRegistrationConvention) を使用することですが、その方法がわかりません。例:

    public class LifecycleConvention : IRegistrationConvention
    {
        public void Process(Type type, Registry registry)
        {
            if (type.GetInterface(typeOf(ISingleton) != null)
                **???? what to do ??!!**
        }
    }

誰か助けてください。

アップデート

私はコンベンションを構築しました:

public class BasicConvention : IRegistrationConvention
{
    public void Process(Type type, Registry registry)
    {
        if (!type.IsAbstract && typeof(ISingleton).IsAssignableFrom(type))
        {
            registry.For(type, new SingletonLifecycle());
        }
        if (!type.IsAbstract && typeof(ITransient).IsAssignableFrom(type))
        {
            registry.For(type, new TransientLifecycle());
        }
    }
}

それは機能しているように見えますが、各クラスをプラグインタイプとして登録します。この場合:

セッション => セッション [シングルトン] BookService => BookService [一時的]

しかし、SessionをISessionとして注入すると... ISessionが登録されていないためインスタンスが見つかりません...しかし、デフォルトの変換を使用できます...そして、動作しますが、インスタンスを一時的なものとして取得します...

WhatDoIHave() を呼び出すと、次のように表示されます。

===============================================================================================================================================================================================================================================================================
PluginType                  Namespace                          Lifecycle     Description                                                                                                                                               Name                                    
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
....
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ISession                     Paf.Application.Session            Transient     Paf.Application.Session ('Paf.Application.Session, Paf.Modules.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null')                        Paf.Application.Session,... (Default)
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
.....
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Session                     Paf.Application                    Singleton     Paf.Application.Session                                                                                                                                (Default)                               
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
...
===============================================================================================================================================================================================================================================================================

私はこれを解決できますか?

4

1 に答える 1

0

OK、StructureMap ソースに移動して、デフォルトの競合を処理する方法を確認しました。

DefaultConventionScanner クラスを見つけました:

public class DefaultConventionScanner : ConfigurableRegistrationConvention
{
    public override void Process(Type type, Registry registry)
    {
        if (!type.IsConcrete()) return;

        var pluginType = FindPluginType(type);
        if (pluginType != null && type.HasConstructors())
        {
            registry.AddType(pluginType, type);
            ConfigureFamily(registry.For(pluginType));
        }
    }

    public virtual Type FindPluginType(Type concreteType)
    {
        var interfaceName = "I" + concreteType.Name;
        return concreteType.GetInterfaces().FirstOrDefault(t => t.Name == interfaceName);
    }
}

プラグイン タイプの登録 ( registry.AddType(pluginType, type) コード行)を変更して、次のように記述できると推測できます。

            if(typeof(ISingleton).IsAssignableFrom(type))
                registry.For(pluginType).Use(type).Singleton();
            else if (typeof(ITransient).IsAssignableFrom(type))
                registry.For(pluginType).Use(type).Transient();
            else
            {
                registry.AddType(pluginType, type);
            }
            ConfigureFamily(registry.For(pluginType));

したがって、pluginType (インターフェイス タイプ) が ISingleton または ITransient の場合、新しいプラグイン タイプを Singleton または Transient として登録します。それ以外の場合は、pluginType を allwais として登録します。

私は仕事を試して知っています!! うん!

考慮すべき点は 1 つだけです。次のような違いがあるかどうかはわかりません。

            registry.AddType(pluginType, type);

および: registry.For(pluginType).Use(type);

WhaDoIHave()の前後の結果を比較しましたが、違いは 1 つだけです。

古い結果:

===============================================================================================================================================================================================================================================================================
PluginType                  Namespace                          Lifecycle     Description                                                                                                                                               Name                                    
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ISession                    Paf.Application.Session            Transient     Paf.Application.Session ('Paf.Application.Session, Paf.Modules.Core, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null')                              Paf.Application.Session,... (Default)
===============================================================================================================================================================================================================================================================================

新しい結果:

===============================================================================================================================================================================================================================================================================
PluginType                  Namespace                          Lifecycle     Description                                                                                                                                               Name                                    
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
ISession                    Paf.Application.Session            Singleton     Paf.Application.Session                                                                                                                                (Default)                               
===============================================================================================================================================================================================================================================================================

新しい結果はわかりました。Singleton です。違いは説明だけです。重要ではないと思います。

アップデート

私の質問のコメントでのスティーブとの会話によると、私は ITransient および ISingleton インターフェイスを使用しないことにしました。実装クラスで属性を使用することにしました。

2 つの属性を作成しました。

[AttributeUsage(AttributeTargets.Class)]
public class SingletonLifecycleAttribute : Attribute
{
}
[AttributeUsage(AttributeTargets.Class)]
public class TransientLifecycleAttribute : Attribute
{
}

そして、私はそれを私のクラスに割り当てました:

public interface ISession   {       int? UserId {get;set;}  }

[SingletonLifecycle]
public class Session : ISession {       public int? UserId {get;set;}   }   

public interface IBookService { ... }

[TransientLifecycle]
public class BookService : IBookService { public BookService(ISession session) { ... }  }

次に、規則を変更しました。

public class BasicConvention : ConfigurableRegistrationConvention
{
    public override void Process(Type type, Registry registry)
    {
        if (!type.IsConcrete()) return;

        var pluginType = FindPluginType(type);
        if (pluginType != null && type.HasConstructors())
        {
            var ci = registry.For(pluginType).Use(type);
            if (type.GetCustomAttributes(true).FirstOrDefault(a => a is TransientLifecycleAttribute) != null)
                ci.Transient();
            if (type.GetCustomAttributes(true).FirstOrDefault(a => a is SingletonLifecycleAttribute) != null)
                ci.Singleton();             
            ConfigureFamily(registry.For(pluginType));
        }
    }

    public virtual Type FindPluginType(Type concreteType)
    {
        var interfaceName = "I" + concreteType.Name;
        return concreteType.GetInterfaces().FirstOrDefault(t => t.Name == interfaceName);
    }
}

今ではすべてがうまくいっていると思います ;) ありがとう、スティーブ!

于 2014-08-16T00:05:00.143 に答える