答案很大程度上取决于原始开发人员是否在他的表单中埋藏了大量的业务逻辑。它们中的逻辑越多,你就越需要付出更多的努力来解决这个问题。
就个人而言,我经常将我的业务逻辑编码为单独的控制器类,这些控制器类具有对具有所需属性和所需事件的接口(而不是表单或全屏 UserControl)的引用。然后在完全独立的项目(每个设备布局一个)中创建我的屏幕并实现 UI 界面。这种方法允许您非常轻松地添加设备。
如果表单中有大量逻辑,则另一个版本是将所有表单转换为基类,以便所有代码甚至事件处理程序都驻留在那里。通过将控件标记为受保护或让基类提供访问它们的虚拟方法,使您的控件可用于子类。然后在每个特定于设备的 UI 项目中,您从基本表单继承。
在这两种方法中,您的附属 UI 项目都会引用带有基类的项目。你打破了循环引用,并通过现在人们称之为控制反转的概念来实现你想要的 UI 的运行时加载,但它实际上只是动态加载你的类型。就个人而言,我一直在为此使用一个简单的配置文件和一个简单的实用程序类,它工作正常。这是我的加载器类。在查看这个时,您还可以使用泛型来摆脱derivesFrom
参数并避免强制转换,但这会让您开始:
public static class ObjectLoader
{
//----------------------------------------------------------------------
// public static methods
//----------------------------------------------------------------------
public static object LoadFromAssembly(
string srcAssembly,
string typeName,
Type derivesFrom)
{
return LoadFromAssembly(srcAssembly, typeName, derivesFrom, true);
}
public static object LoadFromAssembly(
string srcAssembly,
string typeName,
Type derivesFrom,
bool throwOnLoadError)
{
if (srcAssembly == null)
throw new ArgumentNullException("srcAssembly");
else if (srcAssembly.Length == 0)
throw new ArgumentException("Value may not be empty.", "srcAssembly");
else if (typeName == null)
throw new ArgumentNullException("typeName");
else if (typeName.Length == 0)
throw new ArgumentException("Value may not be empty.", "typeName");
else if (derivesFrom == null)
throw new ArgumentNullException("derivesFrom");
object retVal = null;
try
{
string srcAssemblyPath = Path.Combine(AppDir, srcAssembly);
Assembly asm = Assembly.LoadFrom(srcAssemblyPath);
object obj = asm.CreateInstance(typeName);
if (obj != null && derivesFrom.IsAssignableFrom(obj.GetType()))
{
retVal = obj;
}
else if (obj != null) // wrong object, cleanup as needed
{
if (obj is IDisposable)
((IDisposable)obj).Dispose();
}
}
catch (Exception ex)
{
if (throwOnLoadError)
throw;
// otherwise null is returned...
}
return retVal;
}
//----------------------------------------------------------------------
// private static methods
//----------------------------------------------------------------------
private static string AppDir
{
get
{
string appFullPath = Assembly.GetExecutingAssembly().GetName().CodeBase;
return Path.GetDirectoryName(appFullPath);
}
}
}
祝你好运!