4

私たちは少数の顧客向けにアプリを構築しています。それぞれに独自の要件と同様の要件があります。また、すべてのコードを分岐ではなく、同じアプリに保持したいと考えています。また、IF はさまざまな場所にあるため、適切な選択ではありません。

すべての基本クラスを用意する予定です。次に、各顧客は、オーバーライド メソッドが特別なロジックを実行する独自のクラスを持ちます。

これを行う代わりに、コンパイル時にアセンブリをロードするにはどうすればよいですか

public class BaseClass {
    public string getEventId()
}

public class ClassForJohn:BaseClass {
    [override]
    public string getEventId()
}

public class ClassForAdam:BaseClass {
    [override]
    public string getEventId()
}

void UglyBranchingLogicSomewhere() {
   BaseClass  eventOject;
   if("John"==ConfigurationManager.AppSettings["CustomerName"]){
        eventOject = new ClassForJohn();


   }else if("Adam"==ConfigurationManager.AppSettings["CustomerName"]){
        eventOject = new ClassForAdam();


   }else{
        eventOject = new BaseClass ();

   }
  eventId = eventOject.getEventId();
}
4

6 に答える 6

6

これは、プロジェクトの 1 つにプラグイン (アドイン) をロードする方法です。

const string PluginTypeName = "MyCompany.MyProject.Contracts.IMyPlugin";

/// <summary>Loads all plugins from a DLL file.</summary>
/// <param name="fileName">The filename of a DLL, e.g. "C:\Prog\MyApp\MyPlugIn.dll"</param>
/// <returns>A list of plugin objects.</returns>
/// <remarks>One DLL can contain several types which implement `IMyPlugin`.</remarks>
public List<IMyPlugin> LoadPluginsFromFile(string fileName)
{
    Assembly asm;
    IMyPlugin plugin;
    List<IMyPlugin> plugins;
    Type tInterface;

    plugins = new List<IMyPlugin>();
    asm = Assembly.LoadFrom(fileName);
    foreach (Type t in asm.GetExportedTypes()) {
        tInterface = t.GetInterface(PluginTypeName);
        if (tInterface != null && (t.Attributes & TypeAttributes.Abstract) !=
            TypeAttributes.Abstract) {

            plugin = (IMyPlugin)Activator.CreateInstance(t);
            plugins.Add(plugin);
        }
    }
    return plugins;
}

各プラグインは を実装していると思いますIMyPlugin。このインターフェイスは、任意の方法で定義できます。プラグイン フォルダに含まれるすべての DLL をループしてこのメ​​ソッドを呼び出すと、使用可能なすべてのプラグインを自動的にロードできます。

通常、少なくとも 3 つのアセンブリがあります。1 つはインターフェイス定義を含み、このインターフェイス アセンブリを参照するメイン アセンブリ、およびこのインターフェイスを実装する (そしてもちろん参照する) 少なくとも 1 つのアセンブリです。

于 2013-02-28T18:52:22.917 に答える
4

各顧客は独自のexeファイルと構成ファイルを取得し、共有dllがありますか?または、共有exeがあり、各顧客は独自のdllを持っていますか?

次のように、完全なタイプ名を構成に入れることができます。

Shared.exe.config:

<appSettings>
  <add key="CustomerType" value="NamespaceForJohn.ClassForJohn, AssemblyForJohn"/>
</appSettings>

そして、AssemblyForJohn.dllをShared.exeと同じフォルダーに配置します。

次に、次のようなコードで動的にロードできます。

Shared.exe:

var typeString = ConfigurationManager.AppSettings["CustomerType"];
var parts = typeString.Split(',');
var typeName = parts[0];
var assemblyName = parts[1];
var instance = (BaseClass)Activator.CreateInstance(assemblyName, typeName).Unwrap();
于 2013-02-28T18:48:22.600 に答える
1

Unityを使って DI で処理する方法の 1 つを次に示します。

IUnityContainer container = new UnityContainer();
string customerNamespace = ConfigurationManager.AppSettings["CustomerNamespace"];
container.RegisterType(typeof(ISomeInterface), 
                       Type.GetType(customerNamespace+".SomeImplementation"));


// ...

ISomeInterface instance = conainer.Resolve<ISomeInterface>();

ISomeInterface各顧客は、顧客固有の名前空間に独自の実装を持っています。

于 2013-02-28T18:38:20.307 に答える
1

次の方法で、アセンブリから外部型のインスタンスを作成できます。

object obj = Activator.CreateInstance( 
    "External.Assembly.Name", "External.Assembly.Name.TypeName");
BaseClass b = (BaseClass) obj;
b.getEventId();

アセンブリの名前を保存し、構成ファイルまたはその他の適切な場所に入力します。

于 2013-02-28T18:40:00.797 に答える
0

Unityを使用しますが、SimpleFactoryとして使用します。

Unity Framework:同じインターフェイスから2つのクラスをインスタンス化する方法は?

あなたはあなたを保存することができます

私はUnity.2.1.505.2を使用しています(違いが生じる場合に備えて)。

  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
  </configSections>


      <unity>
        <container>
          <register type="IVehicle" mapTo="Car" name="myCarKey" />
          <register type="IVehicle" mapTo="Truck" name="myTruckKey" />
        </container>
      </unity>

これがDotNetコードです。

UnityContainer container = new UnityContainer();

UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
                section.Configure(container);

string myKey = "John";  /* read from config file */ /* with this example, the value should be "myCarKey" or "myTruckKey"  */

IVehicle v1 = container.Resolve<IVehicle>(myKey); 

見る:

http://msdn.microsoft.com/en-us/library/ff664762(v=pandp.50).aspx

http://www.sharpfellows.com/post/Unity-IoC-Container-.aspx

于 2013-02-28T20:11:24.650 に答える