簡體   English   中英

Activator.CreateInstance:類的動態實例化

[英]Activator.CreateInstance: Dynamic Instantiation of Classes

我正在設計一個松耦合的結構。 我想通過String表示的代碼從不同的程序集/命名空間中調用類 我的設計是,每個客戶的業務規則都在不同的程序集上並且彼此不依賴(一個客戶與一個DLL的比率),因此當我對1個客戶的業務規則進行更新時,不會影響其他客戶。 我現在的注意力是在使用Factory Design和Activator.CreateInstance()方法。

這是項目設置(2 + n個DLL)

 namespace Foundation; // where the interfaces/abstract resides
 namespace Factory; // has dependency on Foundation assembly
 namespace Client1; // client1's DLL, no dependency
 namespace Client2; // client2's DLL, no dependency
 The UI // only referenced to the Foundation and Factory not the Clients

實際代碼

 namespace Foundation
 {
   public interface IBusinessRules
   {
     string GetBusinessRule();
  }
 }

 namespace Client1 //DLL for client 1
 {
   public class BusinessRules : Foundation.IBusinessRules
   {
    public string GetBusinessRule()
    {
        return "Client1 Business Rule";
    }
   }
}

namespace Client2 //DLL for client 2
{
   public class BusinessRules : Foundation.IBusinessRules
   {
     public string GetBusinessRule()
     {
        return "Client2 Business Rule";
     }
   }
}


namespace Factory
{
  public static class Invoker<T> where T: Foundation.IBusinessRules
  {
    public static T FetchInstance(string clientCode) 
    {
        return (T)Activator.CreateInstance(Type.GetType(clientCode));   
    }
  }
}


 //sample implementation that generates unhandled Exception
 using Factory;
 using Foundation;
 static void Main(string[] args)
 {
      //the parameter is maintained in the database
       IBusinessRules objClient1 = Invoker<IBusinessRules>.FetchInstance("Client1"); 

       //should call Client1.BusinessRules method
        Console.WriteLine(objClient.GetBusinessRule());  
        Console.Read();

        objClient = Invoker<IBusinessRules>.FetchInstance("Client2");

        //should call Client2.BusinessRules method
        Console.WriteLine(objClient.GetBusinessRule()); 
        Console.Read();      
  }

知道為什么我的樣本不起作用嗎? 還有改進設計的建議嗎? 提前致謝。

怎么樣使用

Expression.Lambda

任何人?

如果您使用FetchInstance(“ Client.BusinessRules”),則如果所有內容都在同一程序集中,則代碼可以正常工作。 如果不是(按照您的設計),則需要提供AssemblyQualifiedName

但是我會做不同的設計。 僅使用“ Client1”作為參數保持通話,但更改Factory的實現。 動態加載給定客戶端的程序集(使用Assembly.Load()或Assembly.LoadFrom()),然后使用clientAssembly.CreateInstance()來確定您的類型。

編輯:原始代碼示例:

namespace Factory
{
  public static class Invoker<T> where T: IBusinessRules
  {
    public static T FetchInstance(string clientCode)
    {
        var clientAssembly = Assembly.LoadFrom(clientCode + ".dll");

        return (T)clientAssembly.CreateInstance(clientCode+".BusinessRules");
    }
  }
}

如果您不知道client-dll中的類名稱,則必須搜索適用的Type,例如,使用clientAssembly.GetTypes()。

多虧了您的幫助,我終於明白了! 我只是修改工廠

 namespace Factory
 {
    public static class Invoker<T> where T : Foundation.IBusinessRules
    {
        public static T FetchInstance(string clientCode)
        {
           Type objType = Type.GetType(clientCode + ".BusinessRules," + clientCode);
           return (T)Activator.CreateInstance(objType);

    }
}

但是我不知道它的效率(性能下降),因為它使用了反射。

您需要使用該類的全名。

例如:

Type.GetType("System.Collections.Generic.Dictionary`2[System.String,[MyType,MyAssembly]]")

如果要從外部程序Activator.CreateInstanceFrom加載類型,則建議使用Activator.CreateInstanceFrom

var typeReference = Activator.CreateInstanceFrom(assemblyPath, fullyQualifiedClassName);
return typeReference.Unwrap() as T;

如果您希望能夠在部署后將業務規則添加為dll並在運行時創建它們,則建議您在應用程序下面有一個業務規則文件夾,在該應用程序中加載所有dll,在每個dll中搜索實現IBusinessRules的所有類型使用反射。 既然您現在可以處理類型了,那么基於名稱創建一個就很容易了,您的項目也可以擴展。

或者,或者將類的程序集限定名稱傳遞給您的方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM