我的程序通过Win32API函数与操作系统进行了大量的交互。现在我想将我的程序迁移到Linux下的Mono下运行(No wine),这需要与操作系统交互的不同实现。
我开始设计一个代码,可以针对不同的平台实现不同的实现,并且可以扩展到未来的新平台。
public interface ISomeInterface
{
void SomePlatformSpecificOperation();
}
[PlatformSpecific(PlatformID.Unix)]
public class SomeImplementation : ISomeInterface
{
#region ISomeInterface Members
public void SomePlatformSpecificOperation()
{
Console.WriteLine("From SomeImplementation");
}
#endregion
}
public class PlatformSpecificAttribute : Attribute
{
private PlatformID _platform;
public PlatformSpecificAttribute(PlatformID platform)
{
_platform = platform;
}
public PlatformID Platform
{
get { return _platform; }
}
}
public static class PlatformSpecificUtils
{
public static IEnumerable<Type> GetImplementationTypes<T>()
{
foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (Type type in assembly.GetTypes())
{
if (typeof(T).IsAssignableFrom(type) && type != typeof(T) && IsPlatformMatch(type))
{
yield return type;
}
}
}
}
private static bool IsPlatformMatch(Type type)
{
return GetPlatforms(type).Any(platform => platform == Environment.OSVersion.Platform);
}
private static IEnumerable<PlatformID> GetPlatforms(Type type)
{
return type.GetCustomAttributes(typeof(PlatformSpecificAttribute), false)
.Select(obj => ((PlatformSpecificAttribute)obj).Platform);
}
}
class Program
{
static void Main(string[] args)
{
Type first = PlatformSpecificUtils.GetImplementationTypes<ISomeInterface>().FirstOrDefault();
}
}
我发现这个设计存在两个问题:
ISomeInterface
的实施具有PlatformSpecificAttribute
。PlatformID
标记,我不知道在Main中使用哪个。使用第一个是丑陋的。如何解决这些问题?你能建议另一种设计吗?
答案 0 :(得分:2)
看看Banshee的来源。根据平台的不同,他们可以根据不同的实现方式进行插入。
答案 1 :(得分:0)
我认为您可以准备两个或更多app.config文件,然后相应地注入平台相关的实现。
最后,将繁重的任务留给平台相关的安装或任何其他部署方法,在Windows上使用Windows版本的app.config,而在Unix上则使用Unix版本。
您可以使用插件架构或其他复杂的解决方案来实现其他不错的功能。
答案 2 :(得分:0)
有趣的是你提到Unity,你考虑过使用Dependency Injection容器吗?我相信Castle Windsor,StructureMap和ninject都可能有一定程度的Mono支持。