Unity in C# for Platform Specific Implementations
My program has heavy interaction with the operating system through Win32API functions. Now I want to migrate my program to run under Mono under Linux (No wi开发者_StackOverflow中文版ne), and this requires different implementations to the interaction with the operating system.
I started designing a code that can have different implementation for different platforms and is extensible for new future platforms.
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();
}
}
I see two problems with this design:
- I can't force the implementations of
ISomeInterface
to have aPlatformSpecificAttribute
. - Multiple implementations can be marked with the same
PlatformID
, and I dont know which to use in the Main. Using the first one is ummm ugly.
How to solve those problems? Can you suggest another design?
Take a look at the source for Banshee. They have a neat way of plugging in different implementations depending on the platform.
I think you can prepare two or more app.config files, and then inject platform dependent implementation accordingly in each.
Finally, leave the heavy task to platform dependent installation or any other deployment methods, when on Windows the Windows version of app.config is used, while on Unix the Unix version is used.
You can use an addin architecture or other complicated solutions to achieve other nice features.
Funny you mention Unity, have you considered using a Dependency Injection container? I believe Castle Windsor, StructureMap and ninject all may have some degree of Mono support.
精彩评论