2011-08-25 41 views
0

我有一個Activator.CreateInstanc的小問題,讓我先展示一些代碼。未找到C#.NET構造函數,反射

public class CommandLoader 
{ 
    public List<IPosCommand> LoadCommands(string path, ApplicationRepository applicationRepository) 
    { 
     object[] args = new object[] {applicationRepository}; 

     List<IPosCommand> commands = new List<IPosCommand>(); 
     string[] possiableCommands = Directory.GetFiles(path, "*.dll"); 

     foreach (string file in possiableCommands) 
     { 
      IPosCommand command = GetCommand(file, args); 
      if(command != null) 
       commands.Add(command); 
     } 
     return commands; 
    } 
    private IPosCommand GetCommand(string file,object[] args) 
    { 
     try 
     { 
      Assembly assembly = Assembly.LoadFrom(file); 
      foreach (Type type in assembly.GetTypes()) 
      { 
       bool isPosCommand = IsTypePosCommand(type); 

       if (isPosCommand) 
       { 

           IPosCommand command = (IPosCommand)Activator.CreateInstance(type, args); 
           return command; 

       } 
       } 

      } 
     } 
     catch (ReflectionTypeLoadException) 
     { 
     } 
     return null; 
    } 

    private bool IsTypePosCommand(Type type) 
    { 
     return type.GetInterfaces().Any(x => x == typeof (IPosCommand)); 
    } 

上面是加載程序代碼,接下來是實現IPosCommand的代碼。

public class SignOffCommand : IPosCommand 
{ 
    private ApplicationRepository applicationRepository; 

    public SignOffCommand(ApplicationRepository applicationRepository) 
    { 
     this.applicationRepository = applicationRepository; 
    } 
    public CommandInfomation CommandInfomation { get; set; } 
    public bool PlaceAtTopAndWaitForNextCommand { get; set; } 
    public void Execute(object Sender, string commandText) 
    { 
     if (commandText == "SIGNOFF") 
     { 
      ISalesView view = applicationRepository.Get<ISalesView>(); 
      if (view != null) 
      { 
       IOperatorSessionManager sessionManager = applicationRepository.Get<IOperatorSessionManager>(); 
       if (sessionManager != null) 
       { 
        sessionManager.OnOperatorSignOff(view.CurrentOperator); 
       } 

       view.CurrentOperator = null; 

       throw new ForceStopException(); 
      } 
     } 
    } 

    public string GetCommandText 
    { 
     get 
     { 
      return "SIGNOFF"; 
     } 
    } 
    public string CommandName 
    { 
     get 
     { 
      return "SIGNOFF"; 
     } 
    } 
} 

使用上面的代碼我得到一個missingmethodexception,說它找不到構造函數。 現在奇怪的部分是,如果我使用此代碼,它工作正常。

public enum CommandType{ 
    System, 
    User 
} 

[Serializable] 
public class CommandInfomation 
{ 
    public string DllName { get; set; } 
    public string FullName { get; set; } 
    public CommandType CommandType { get; set; } 
} 

    public List<IPosCommand> LoadCommands(ApplicationRepository applicationRepository) 
    { 
     List<CommandInfomation> commandInfomations = 
      AppDataSerializer.Load<List<CommandInfomation>>("CommandInfomation.xml"); 


     List<IPosCommand> commands = new List<IPosCommand>(); 
     foreach (CommandInfomation infomation in commandInfomations) 
     { 

      Assembly assembly = Assembly.LoadFrom(infomation.DllName); 

      object[] args = new Object[] {applicationRepository}; 
      Type type = assembly.GetType(infomation.FullName, false); 

      IPosCommand command = (IPosCommand) Activator.CreateInstance(type, args); 

      command.CommandInfomation = infomation; 

      commands.Add(command); 

     } 
     return commands; 
    } 

裝載機的兩個版本的作用有點不同,首先掃描目錄的所有.dll文件 ,然後檢查,看看是否類型實現了IPosCommand,第二加載程序代碼,知道DLL文件名稱和完整的類型名稱。 任何幫助將非常感激。

+1

驗證界面如果您有類型和同樣'FullName',但不同的程序集的版本,您可能會收到一個錯誤。我以前通過使用動力學來克服版本控制的類似問題(但那只是爲了測試,我不會推薦它用於生產代碼)。 –

+0

我通過更改string [] possiableCommands = Directory.GetFiles(path,「* .dll」)修復了此問題; to string [] possiableCommands = Directory.GetFiles(path,「* Command.dll」); 我認爲當我加載並檢查其他沒有實現IPosCommand的dll時,一定會有一些奇怪的依賴關係,哦,它仍然有點奇怪,但至少它的排序。 謝謝大家。 – Jamie

回答

1

在第一個加載器中,而不是使用您的實現IsTypePosCommand嘗試使用return type.IsAssignableFrom(typeof(IPosCommand))。它可能無法正確確定類型。

+0

嗯有趣的是,使用該方法,它找不到IPosCommand的任何植入。 – Jamie

1

程序集中可能有類繼承IPosCommand,但沒有構造函數帶有一個類型爲applicationRepository的參數。試着用typeof(WinformRenderer).GetConstructor(Type[] types)更精確地過濾掉級還與typeof(WinformRenderer).GetInterface(name, true)

+0

謝謝,每個支持IPosCommand的類接受ApplicationRepository作爲它的參數,並且只有一個構造函數。另外,第二個加載器可以和所有的IPosCommands一起工作,我覺得很奇怪。 – Jamie

相關問題