Так что в моем исходном посте я получал ошибку компиляции на строке «builder.RegisterInstance (Activator.CreateInstance (repoClass)); Это было связано с тем, что repoClass не мог смотреть на repoInterface во время разработки. Поэтому я создал динамический класс времени выполнения, который получает фактические типы из repoClass и repoInterface во время выполнения, затем компилирует и выполняет класс «на лету», чтобы вернуть ContainerBuilder из моего Assembly.LoadFile.
public class RuntimeContainerBuilder
{
public static object Evaluate(ContainerBuilder builder, Type controller, Type repoInterface, Type repoClass, Assembly assembly)
{
CSharpCodeProvider c = new CSharpCodeProvider();
ICodeCompiler icc = c.CreateCompiler();
CompilerParameters cp = new CompilerParameters();
cp.ReferencedAssemblies.Add("system.dll");
cp.ReferencedAssemblies.Add(AssemblyDirectory + "\\System.Web.Http.dll");
cp.ReferencedAssemblies.Add(AssemblyDirectory + "\\Autofac.dll");
cp.ReferencedAssemblies.Add(AssemblyDirectory + "\\Autofac.Integration.WebApi.dll");
cp.ReferencedAssemblies.Add(@"E:\MainTrunk2\LeadGenFramework\trunk\LeadGenFramework.Web.Api\LeadGenFramework.Web.Api.Controller.TitleLoan\bin\LeadGenFramework.Web.Api.TitleLoan.dll");
cp.CompilerOptions = "/t:library";
cp.GenerateInMemory = true;
StringBuilder sb = new StringBuilder("");
sb.Append("using System;\n");
sb.Append("using Autofac;\n");
sb.Append("using System.Web.Http;\n");
sb.Append("using System.Web.Http.Controllers;\n");
sb.Append("using Autofac.Integration.WebApi;\n");
sb.Append(string.Format("using {0};\n", assembly.ManifestModule.Name.Replace(".dll","")));
sb.Append("namespace LeadGenFramework.Web.Api{ \n");
sb.Append("public class DynamicBuild{ \n");
sb.Append("public ContainerBuilder Build(ContainerBuilder obj){\n");
sb.Append(string.Format("obj.RegisterApiControllers(typeof({0}).Assembly).PropertiesAutowired();\n",controller.Name));
sb.Append(string.Format("obj.RegisterInstance<{0}>(new {1}());\n", repoInterface.Name, repoClass.Name));
sb.Append("return obj; \n");
sb.Append("} \n");
sb.Append("} \n");
sb.Append("}\n");
string s1 = sb.ToString();
CompilerResults cr = icc.CompileAssemblyFromSource(cp, s1);
if (cr.Errors.Count > 0)
{
//Factory.LogManager.MainProcessLogger.Info(string.Format("DynamicFormatScriptEngine:Evaluate(): Error: {0}, Code: {1}", cr.Errors[0], s1));
return null;
}
Assembly a = cr.CompiledAssembly;
object o = a.CreateInstance("LeadGenFramework.Web.Api.DynamicBuild");
Type t = o.GetType();
MethodInfo mi = t.GetMethod("Build");
object s = mi.Invoke(o,new object[]{builder});
return s;
}
Теперь мой WebApiConfig, как так ... видеть линию "RuntimeContainerBuilder.Evaluate (строитель, контроллер, repoInterface, repoClass, ASM)"
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.EnableSystemDiagnosticsTracing();
ContainerBuilder builder = new ContainerBuilder();
//string WebApisPath = ConfigurationManager.AppSettings["AutoFac_WebApiControllerAssembliesPath"];
string titleLoanAsm = ConfigurationManager.AppSettings["WebApi_TitleLoanAssembly"];
//Assembly asm = Assembly.LoadFile(AssemblyDirectory.Replace("\\bin", "") + WebApisPath + titleLoanAsm);
Assembly asm = Assembly.LoadFile(AssemblyDirectory + "\\" + titleLoanAsm);
List<Type> exportedTypes = new List<Type>(asm.GetExportedTypes());
Type controller = exportedTypes.FirstOrDefault(t => !t.IsAbstract && typeof(ApiController).IsAssignableFrom(t));
if (controller == null)
throw new ObjectNotFoundException(string.Format("Contoller not found in assembly {0}.", asm.FullName));
Type repoClass = exportedTypes.FirstOrDefault(x => x.IsClass && x.Name.Contains("LGF"));
if (repoClass == null)
throw new ObjectNotFoundException(string.Format("No repositories found for controller"));
Type repoInterface = repoClass.GetInterfaces().FirstOrDefault(x => x.IsInterface && x.Name.Contains("LGF"));
if (repoInterface == null)
throw new ObjectNotFoundException(string.Format("Interface not found for class {0}. Ensure class has and interface implemented with a name that contains LGF", repoClass.Name));
RuntimeContainerBuilder.Evaluate(builder, controller, repoInterface, repoClass, asm);
IContainer container = builder.Build();
AutofacWebApiDependencyResolver resolver = new AutofacWebApiDependencyResolver(container);
config.DependencyResolver = resolver;
}
Следующий шаг, чтобы сделать его более generic, чтобы загружать сборки в массив и настраивать RuntimeContainerBuilder для каждого ... затем builder.Build должен правильно разрешать и активировать все. Моя конечная цель для этого прототипа - перетащить сборки и заставить WebApi динамически их подбирать.
Нет кубиков ... Я получаю 404 на своем модульном тесте на WebApi. – chdev77
Что такое 404 связано с регистрацией Autofac? – Nathan
404 Not Found ... посмотреть его [ссылка] (http://en.wikipedia.org/wiki/HTTP_404). Это означает, что он не регистрируется правильно. Если я переведу контроллер и наберусь на одного и того же осла. как проходит тест WebApi, если я переведу их в отдельную задницу. и отражать типы, а не работать. Как я уже сказал, я новичок в AutoFac. Может быть, вы могли бы уточнить, пожалуйста? – chdev77