C# 如何调用在运行时选择的几个静态类之一的方法?
我使用几个类来提供服务,例如,有一个类用于FTP,另一个类用于HTTP,这两个类都实现了相同的方法,但都是根据协议定制的:C# 如何调用在运行时选择的几个静态类之一的方法?,c#,reflection,static-methods,C#,Reflection,Static Methods,我使用几个类来提供服务,例如,有一个类用于FTP,另一个类用于HTTP,这两个类都实现了相同的方法,但都是根据协议定制的: public static class FtpProvider { public static string GetString () { return "1"; } } public static class HttpProvider { public static string GetString () { return "2";
public static class FtpProvider { public static string GetString () { return "1"; } }
public static class HttpProvider { public static string GetString () { return "2"; } }
我需要一个简单的服务选择器来切换提供服务的静态类。我使用类型变量来保存当前提供程序,例如
Type _type = (condition) ? typeof (FtpProvider) : typeof (HttpProvider);
然后,我使用反射调用所选类的方法。整个代码:
class Program {
static void Main () {
Type _type = (new Random ().NextDouble () > .5) ? typeof (FtpProvider) : typeof (HttpProvider);
string _methodName = nameof (FtpProvider.GetString);
MethodInfo _method = _type.GetMethod (
_methodName,
BindingFlags.Public | BindingFlags.Static | BindingFlags.FlattenHierarchy);
object _result = _method.Invoke (null, null);
Console.WriteLine (_result.ToString ()); Console.ReadKey ();
}
}
public static class FtpProvider { public static string GetString () { return "1"; } }
public static class HttpProvider { public static string GetString () { return "2"; } }
这确实有效,但在运行时切换静态类型时,这确实是一段难看的代码,因为它只是用来替换像currentProvider.GetString()
这样的调用。所以我想知道:
- 如果有更好的切换静态类提供程序的设计
- 如果这种方式可以接受,代码可以简化吗
静态类型不支持继承或Liskov替换。他们不是故意的。这就是你的代码如此混乱的原因——你所做的事情非常奇怪。如果您想让这些提供程序变得简单,那么应该将它们实现为具有公共接口的常规实例类 这就是说,如果您完全无法使用静态类,那么使用提供者映射是一种更容易的方法
var map = new Dictionary<string,Func<string>>
{
{ "HTTP", HttpProvider.GetString },
{ "FTP", FtpProvider.GetString }
};
下面是一个使用单例模式而不是
静态类的示例,以及一个实现所需功能的接口。不需要思考。您可以从静态CurrentProvider
属性访问“provider”(或者根据自己的喜好更改访问权限)
希望您的提供程序类重叠足够多,以便有一个公共接口可以与它们一起使用。然后,你的应用程序的其余部分就不必知道实际的提供商类型;它们只是与界面交互
注意,我已经为singletonprivate
创建了默认构造函数,因此获取此类实例的唯一方法是调用static instance属性。因此,它们的行为类似于静态类。(如果您真的不希望人们在静态实例属性之外构造它们,您也可以考虑标记这些代码>密封< /代码>)
您仍然可以通过切换条件变量来切换提供程序。我建议不要使用bool
,而是使用enum
,不过您可以在以后修改条件的工作方式
using System;
namespace SomeNamespace
{
public class Program
{
static void Main()
{
Condition = new Random().NextDouble() > .5;
Console.WriteLine(CurrentProvider.GetString()); Console.ReadKey();
}
static bool Condition;
static IProvider CurrentProvider => Condition ? FtpProvider.Instance as IProvider : HttpProvider.Instance as IProvider;
}
// interface allows for multiple provider types
public interface IProvider
{
string GetString();
}
public class FtpProvider : IProvider
{
// use Lazy<T> to implement Singleton pattern
private static readonly Lazy<FtpProvider> lazy = new Lazy<FtpProvider>(() => new FtpProvider());
public static FtpProvider Instance
{
get
{
return lazy.Value;
}
}
// don't allow normal construction of this class
// force everyone to use Instance
private FtpProvider() { }
public string GetString() => "1";
}
public class HttpProvider : IProvider
{
// use Lazy<T> to implement Singleton pattern
private static readonly Lazy<HttpProvider> lazy = new Lazy<HttpProvider>(() => new HttpProvider());
public static HttpProvider Instance
{
get
{
return lazy.Value;
}
}
// don't allow normal construction of this class
// force everyone to use Instance
private HttpProvider() { }
public string GetString() => "2";
}
}
使用系统;
名称空间名称空间
{
公共课程
{
静态void Main()
{
条件=new Random().NextDouble()>.5;
Console.WriteLine(CurrentProvider.GetString());Console.ReadKey();
}
静态布尔条件;
静态IProvider CurrentProvider=>条件?FtpProvider.Instance作为IProvider:HttpProvider.Instance作为IProvider;
}
//接口允许多种提供程序类型
公共接口IProvider
{
字符串GetString();
}
公共类FtpProvider:IProvider
{
//使用Lazy实现单例模式
private static readonly Lazy Lazy=new Lazy(()=>new FtpProvider());
公共静态FtpProvider实例
{
收到
{
返回lazy.Value;
}
}
//不允许该类的正常构造
//强制所有人使用实例
私有FtpProvider(){}
公共字符串GetString()=>“1”;
}
公共类HttpProvider:IProvider
{
//使用Lazy实现单例模式
private static readonly Lazy Lazy=new Lazy(()=>new HttpProvider());
公共静态HttpProvider实例
{
收到
{
返回lazy.Value;
}
}
//不允许该类的正常构造
//强制所有人使用实例
私有HttpProvider(){}
公共字符串GetString()=>“2”;
}
}
为什么这些类必须是静态的?您可以使用一个接口来包含GetString
方法,并让两个类实现相同的接口。然后,其他一些代码可以选择要实例化和使用的类类型,但它会作为接口类型传递。如果希望每个提供程序类型只有一个实例,那么可以使用Singleton模式。好的,这很有趣,我需要每个服务有一个映射,可能超过20个,但这是一个很好的重新启动,谢谢。好的,我尝试了一下,发现了两个简单的问题:实例创建和无法使用静态方法实现接口。我必须说,没有是不可能的。如果实例创建是一个问题,那么您可能需要更新您的问题,提供更多关于为什么必须使所有内容都是静态的信息。是不是因为您无法控制静态类,比如说因为它们在编译库中?
using System;
namespace SomeNamespace
{
public class Program
{
static void Main()
{
Condition = new Random().NextDouble() > .5;
Console.WriteLine(CurrentProvider.GetString()); Console.ReadKey();
}
static bool Condition;
static IProvider CurrentProvider => Condition ? FtpProvider.Instance as IProvider : HttpProvider.Instance as IProvider;
}
// interface allows for multiple provider types
public interface IProvider
{
string GetString();
}
public class FtpProvider : IProvider
{
// use Lazy<T> to implement Singleton pattern
private static readonly Lazy<FtpProvider> lazy = new Lazy<FtpProvider>(() => new FtpProvider());
public static FtpProvider Instance
{
get
{
return lazy.Value;
}
}
// don't allow normal construction of this class
// force everyone to use Instance
private FtpProvider() { }
public string GetString() => "1";
}
public class HttpProvider : IProvider
{
// use Lazy<T> to implement Singleton pattern
private static readonly Lazy<HttpProvider> lazy = new Lazy<HttpProvider>(() => new HttpProvider());
public static HttpProvider Instance
{
get
{
return lazy.Value;
}
}
// don't allow normal construction of this class
// force everyone to use Instance
private HttpProvider() { }
public string GetString() => "2";
}
}