C# MVC:如何在运行时获取控制器及其依赖项
因此,我正在构建一个可通过插件扩展的MVC web应用程序。 插件可以放在文件夹中,如果应用程序重新启动,它们就会被加载。我遇到的问题是插件中的一些/大多数控制器都有带参数的构造函数。 我已经有一个自定义控制器工厂,可以在运行时创建必要的控制器,但问题在于控制器的注册。 我目前有:C# MVC:如何在运行时获取控制器及其依赖项,c#,asp.net-mvc,asp.net-mvc-4,plugins,C#,Asp.net Mvc,Asp.net Mvc 4,Plugins,因此,我正在构建一个可通过插件扩展的MVC web应用程序。 插件可以放在文件夹中,如果应用程序重新启动,它们就会被加载。我遇到的问题是插件中的一些/大多数控制器都有带参数的构造函数。 我已经有一个自定义控制器工厂,可以在运行时创建必要的控制器,但问题在于控制器的注册。 我目前有: CustomControllerFactory factory = new CustomControllerFactory(); factory.RegisterFactoryMethod<MyControll
CustomControllerFactory factory = new CustomControllerFactory();
factory.RegisterFactoryMethod<MyController>(() => new MyController(_myDependecy));
控制器工厂为:
public class CustomControllerFactory : DefaultControllerFactory
{
private Dictionary<string, Func<IController>> _factoryMethods = new Dictionary<string, Func<IController>>();
public void RegisterFactoryMethod<T>(Func<IController> factoryMethod)
where T : IController
{
string controllerName = ConvertToControllerName<T>();
if (_factoryMethods.ContainsKey(controllerName))
throw new Exception(String.Format("FactoryMethod for controller '{0}'is already registered.", controllerName));
_factoryMethods[controllerName] = factoryMethod;
}
private string ConvertToControllerName<T>()
{
string fullName = typeof (T).Name;
//Cut of "Controller"
return fullName.Substring(0, fullName.Length - 10);
}
public override IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
{
if (_factoryMethods.ContainsKey(controllerName))
return _factoryMethods[controllerName]();
return base.CreateController(requestContext, controllerName);
}
}
但这需要我知道在编译时添加哪些控制器和哪些依赖项。
如何在运行时从其程序集获取控制器及其依赖项?我最终找到了一个解决方案,但它不是完全通用的,因为我只考虑具有一个已知依赖项的构造函数
Type[] controllers = assembly.GetTypes().Where(x => x.BaseType == typeof(Controller)).ToArray();
foreach (Type controller in controllers)
{
ConstructorInfo[] constructors = controller.GetConstructors();
foreach (var constructor in constructors)
{
RegisterControllerConstructor(constructor,_MyDependecy,controller,factory);
}
}
}
private void RegisterControllerConstructor(ConstructorInfo constructor, MyDependecy _MyDependecy, Type controller, CustomControllerFactory factory)
{
ParameterInfo[] parameters = constructor.GetParameters();
Type[] paraTypes = parameters.Select(p => p.ParameterType).ToArray();
MethodInfo method =
factory.GetType().GetMethod("RegisterFactoryMethod").MakeGenericMethod(controller);
if (paraTypes.Length == 1 && paraTypes[0] == _MyDependecy.GetType())
{
var param = new object[1];
Func<IController> action = () =>
{
return Activator.CreateInstance(controller, _MyDependecy) as IController;
};
param[0] = action;
method.Invoke(factory, param);
}
}