我们的解决方案提供了一个DLL,用于通过以太网与某些硬件进行通信。我们已经创建了第二个DLL,可以用来模拟硬件,这样我们的开发人员就不需要在每个办公桌上都有所说的硬件。
软件不应该知道它是使用真实硬件还是模拟器。如何在不需要重新编译解决方案的情况下交换引用?
我们可以只指定两个引用相同,只需注册/取消注册我们想要引用的正确的DLL吗?
[更新] 注意:第一个DLL是我们无法访问的第三方DLL。第二个DLL是我们用C ++创建的。我们的应用程序是用C#编写的。
答案 0 :(得分:2)
使两个DLL实现一个通用接口(ICommunicateToYourHardware)并编写应用程序代码以通过反射而不是通过引用来发现DLL。
每次请求添加示例
此示例中的接口称为IAuthenticate,但您可以使用其中的任何接口。在这种情况下,我实际上正在寻找任何数量的IAuthenticate类。在您的情况下,如果不同的DLL放置在相同的相对路径中,则相同的编译将引入不同的DLL。
// We need a container for the DLL files that we find and then a container for the instances of
// the plug ins created from the dlls. In this test we are only really looking for One such plug in
// but I prefer to use collections for such things as it allows for a more scalable design. This technique
// works for 1, 100, or more plugins and/or methods.
private List<string> _DLLS;
private List<iAuthenticate> _PlugIns;
private int LoadPlugIns(string Path)
{
/// Within the designated Path (and in all subdirectories) locate all .dll files and put the path
/// to these files in a collection.
GetDLLS(Path);
foreach (string dirName in Directory.GetDirectories(Path))
{
LoadPlugIns(dirName);
}
// For each .dll file, inspect it (using reflection) to determine if it is of the iAuthenticate Type
// if it is, create and instance of the object and store it in a collection, and assign a delegate to
// invoke its Authenticate method from the host application.
foreach (string DLL in _DLLS)
{
Assembly myAssembly = Assembly.LoadFrom(DLL);
Type[] Types = myAssembly.GetTypes();
foreach (Type myType in Types)
{
Type T = myType.GetInterface("iAuthenticate");
if (T != null)
{
if (_PlugIns == null) { _PlugIns = new List<iAuthenticate>(); }
_PlugIns.Add((iAuthenticate)myAssembly.CreateInstance(myType.FullName));
}
}
foreach (iAuthenticate iAuth in _PlugIns)
{
this.Authorize += iAuth.Authenticate;
}
}
return _PlugIns.Count;
}
private void GetDLLS(string Path)
{
if (_DLLS == null){_DLLS = new List<string>();}
foreach (string filename in Directory.GetFiles(Path, "*.dll"))
{
_DLLS.Add(filename);
}
}
一旦我们通过反射获得了引用集,我们就可以调用它的方法:
private void btnLogon_Click(object sender, EventArgs e)
{
try
{
if (Authorize.Invoke(txtUsername.Text, txtPassword.Text, txtPath.Text))
{
this.BackgroundImage = TelefloraDemo.Properties.Resources._189469;
this.pnlLogon.Visible = false;
MessageBox.Show("You have Logged On!");
}
}
catch (AuthenticationException aex)
{
DemoCode.LogException(aex);
MessageBox.Show(aex.ToString());
}
catch (Exception ex)
{
DemoCode.LogException(ex);
MessageBox.Show("No Authenticator");
}
}
public delegate bool Authenticate(string Username,string Password,string Path);
public event Authenticate Authorize;
现在,显然你的里程可能会有所不同,但这应该会让你走上成功之路。 (是的,还有其他方式,我喜欢这个..)
答案 1 :(得分:2)
MEF(托管扩展性框架)使得执行此类操作变得非常容易。只需确保您的真实和模拟界面导出相同的合同并使用MEF组合来注入所需的版本。
这是simple example如何使用它。
答案 2 :(得分:0)
这来自MSDN
您可以重定向装配绑定 引用另一个版本的 通过使用中的条目进行汇编 应用程序或机器配置 文件。您可以将引用重定向到 .NET Framework程序集,第三方 装配件或您自己的装配件 应用。每个版本的.NET Framework具有机器配置 文件和任何重定向信息 在该文件中影响所有应用程序 在该版本的.NET下运行 框架。
答案 3 :(得分:0)
引用两者并使用工厂类创建适当的接口。然后,您可以使用某种外部机制:配置文件,注册表项,计算机名称,构建标识符等...以使工厂发出正确的接口。