2

DI に関して助けが必要ですが、以前に DI を使用したことがないので、概念は私にとって新しいものです。いくつかのパラメータに基づいてログ データを DB またはフラット ファイルまたはイベント ログに保存したい

たとえば、国コードが GBR の場合、イベント ログは DB に保存されます。国コードが USA の場合、イベント ログはフラット ファイルに保存されます。国コードが USA の場合、イベント ログは Windows イベント ログに保存されます。

上記の問題をDIパターンで実装する同様のコードを取得しました。ここにコードがあります

public interface ILog
{
  void Log(string text);
}

次に、クラスでこのインターフェースを使用します

public class SomeClass
{
  [Dependency]
  public ILog Log {get;set;}
}

実行時にそれらの依存関係を注入する

public class SomeClassFactory
{
  public SomeClass Create()
  {
    var result = new SomeClass();
    DependencyInjector.Inject(result);
    return result;
  }
}

インスタンスは app.config で構成されます。

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <configSections>
    <section name ="unity"
             type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection,
              Microsoft.Practices.Unity.Configuration"/>
  </configSections>
  <unity>
    <typeAliases>
      <typeAlias alias="singleton"
                 type="Microsoft.Practices.Unity.ContainerControlledLifetimeManager,Microsoft.Practices.Unity" />
    </typeAliases>
    <containers>
      <container>
        <types>
          <type type="MyAssembly.ILog,MyAssembly"
                mapTo="MyImplementations.SqlLog, MyImplementations">
            <lifetime type="singleton"/>
          </type>
        </types>
      </container>
    </containers>
  </unity>
</configuration>

しかし、この上記のコードの問題は、一度に 1 つのことしか実行しないことです。DB 用のアセンブリ実装がある場合は DB に保存され、フラット ファイル用のアセンブリ実装がある場合はフラット ファイルに保存されます。

しかし、私の要件は、国コードに基づいてデータを保存したいなど、ビットの違いは同じです。その結果、コードと構成ファイルで変更する必要があるものは、国コードに基づいてどこにでもデータを保存できます。コードとコンセプトについて教えてください。ありがとう

4

2 に答える 2

3

The reason a DI framework is useful is to avoid needing to make a lot of boilerplate factory implementations, like this:

public class SomeFactory
{
    public SomeClass GetSomeClass()
    {
          return new SomeClass(new SomeDep1(), new SomeDep2(new SomeInnerDep()));
    }
}

If you don't have a simple need in a factory, don't shy away from just writing what you need. In your example:

public class ILogFactory
{
  public ILog Create(CountryCode code)
  {
     if(code == CountryCode.GBR) return new EvenLogger();

     if(code == CountryCode.UK) return new DatabaseLogger(_providerFactory());

     ///etc...
  }
}

EDIT: Notice also that I wrote an ILog factory instead of a SomeClassFactory. That way users of the factory couple to an interface, rather than a concrete instance. This is a really helpful practice in DI and generally, as it allows you to substitute desired concrete types.

于 2013-01-10T14:24:57.637 に答える
2

2 つのことを行う必要があります。1) Unity コンテナーに特定の名前で 2 つのマッピングを登録します。次のように xml 構成を変更します。

<type type="MyAssembly.ILog,MyAssembly"
            mapTo="MyImplementations.SqlLog, MyImplementations"
            name="sql">
        <lifetime type="singleton"/>
      </type>
<type type="MyAssembly.ILog,MyAssembly"
            mapTo="MyImplementations.FileLog, MyImplementations"
            name="file">
        <lifetime type="singleton"/>
      </type>

(「type」要素の「name」属性に注意してください)

そして、依存関係をそのように解決します (DependencyInjector クラスがわからないので、Unity コンテナー (Microsoft.Practices.Unity.IUnityContainer) を使用します):

// create and initialize unity container once somewhere in startup code.
var сontainer = new UnityContainer();
container.LoadConfiguration(); // load unity configuration from application xml config 

// then use container to resolve dependencies.
if (CountryCodeSaysToUseDb())
   return container.Resolve<MyAssembly.ILog>("sql");
if (ContryCodeSaysToUseFile())
   return container.Resolve<MyAssembly.ILog>("file");

ただし、独自のコード内で特定の実装を明示的に選択すると、DI パターンが壊れてしまうため、注意してください。

于 2013-01-10T14:46:10.930 に答える