我们需要能够将新项目/ dll放入我们的主项目中,并让主项目接收它们并能够使用它们。决定使用AutoFac来满足这种需求。这样主要项目就不需要直接引用我们想要使用的任何其他项目/ dll。这是global.asax:
var builder = new ContainerBuilder();
var directoryName = HttpContext.Current.Server.MapPath("~/bin/");
var cfg = new ModularityLoader(new ModularityConfig(Path.Combine(directoryName, @"Modules")), new Log4NetLogger(typeof(ModularityConfig)));
cfg.RegisterModulesFromCatalog(builder);
builder.RegisterType<AssembliesResolver>().AsImplementedInterfaces();
builder.RegisterType<AppsSecurityFeatureResolver>().AsImplementedInterfaces();
builder.RegisterType<FeaturesAutofacAuthoriztationFilter>()
.AsWebApiAuthorizationFilterFor<ApiController>().InstancePerApiRequest();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);
builder.RegisterControllers(typeof(MvcApplication).Assembly);
Container = builder.Build();
我们在将其dll复制到主项目的bin目录中的所有项目上都有后期构建事件。所有的dll都加载到 var cfg = new ModularityLoader 。
见图片:
builder.Build()在我们项目中实现Autofac.Module的任何dll中调用以下类,如下所示:
public class AutofacModuleConfig : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
builder.RegisterApiControllers(typeof(AutofacModuleConfig).Assembly);
}
}
这是SignalR的问题所在。我想将RouteTable.Routes.MapHubs()放入AutofacModuleConfig,但SignalR 2.0.0+不再支持此功能。相反,它希望您创建一个这样的Startup类:
[assembly: OwinStartup("SignalRConfig", typeof(KL.Apps.TestHarness.SignalR.Startup))]
namespace KL.Apps.TestHarness.SignalR
{
public static class Startup
{
public static void Configuration(IAppBuilder app)
{
app.MapSignalR("/signalr", new HubConfiguration());
}
}
}
注意:为了实现这一点,我将以下内容添加到web.config中:
<add key="owin:appStartup" value="SignalRConfig" />
SignalR还需要这样的Hub类:
[HubName("BatchHub")]
public class BatchHub : Hub
{
public void RemoveBatchRow(Guid batchId)
{
Clients.All.RemoveBatchRow(batchId);
}
}
在我的主项目中使用Startup类和Hub类可以很好地工作。但是,由于AutoFac的独特性,我的外部dll中的所有Hub都没有被加载。我正在考虑尝试找到一种方法来强制AutofacModuleConfig.Load接受RouteTable.Routes.MapHubs(),但添加此行会破坏代码。
我想回到SignalR的早期版本,所以我可以使用RouteTable.Routes.MapHubs(),但我真的想使用最新版本。
有什么想法吗?
提前致谢。
我发现了这个:https://code.google.com/p/autofac/wiki/SignalRIntegration 这似乎是问题的答案。但是,即使在安装Autofac.SignalR NuGet包之后,RegisterHubs也不存在于构建器对象之外......
var builder = new ContainerBuilder();
builder.RegisterHubs(Assembly.GetExecutingAssembly());
所以这就是我的AutofacModuleConfig现在的样子,但我的集线器仍然没有出现在javascript中。
namespace OurName.IOC
{
public class AutofacModuleConfig : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
AutofacSignalRConfig.Load(builder);
builder.RegisterApiControllers(typeof(AutofacModuleConfig).Assembly);
}
}
}
namespace Autofac.Integration.SignalR
{
public static class AutofacSignalRConfig
{
public static void Load(ContainerBuilder builder)
{
builder.RegisterHubs(Assembly.GetExecutingAssembly());
}
}
}
仍然没有工作。在javascript中,我无法看到我的中心。
$(document).ready(function(){
var myHub = $.connection.BatchHub;
});
myHub为空。
昨晚试了一下。我删除了AutofacSignalRConfig,这就是主要的Global.asax现在的样子:
var builder = new ContainerBuilder();
var directoryName = HttpContext.Current.Server.MapPath("~/bin/");
var cfg = new ModularityLoader(new ModularityConfig(Path.Combine(directoryName, @"Modules")), new Log4NetLogger(typeof(ModularityConfig)));
cfg.RegisterModulesFromCatalog(builder);
builder.RegisterType<AssembliesResolver>().AsImplementedInterfaces();
builder.RegisterType<AppsSecurityFeatureResolver>().AsImplementedInterfaces();
builder.RegisterType<FeaturesAutofacAuthoriztationFilter>()
.AsWebApiAuthorizationFilterFor<ApiController>().InstancePerApiRequest();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);
builder.RegisterControllers(typeof(MvcApplication).Assembly);
foreach (var assembly in cfg.LoadedAssemblies)
{
var hubs = builder.RegisterHubs(assembly);
}
Container = builder.Build();
GlobalHost.DependencyResolver = new Autofac.Integration.SignalR.AutofacDependencyResolver(Container);
注意我是如何尝试获取cfg的输出(它是bin文件夹中找到的所有程序集的集合),然后通过它们进行操作以便在每个文件夹上执行builder.RegisterHubs。尽管如此,仍然没有从任何一个组件中拿起我的集线器。
我的每个导入的dll中是否还需要一个Startup类?如果是这样,我该如何调用呢?
尝试过这一点也没有成功:
foreach (var assembly in cfg.LoadedAssemblies)
{
//var hubs = builder.RegisterHubs(assembly);
var a = assembly.GetExportedTypes().Where(x => x.BaseType == typeof (Hub));
foreach (var x in a)
{
builder.RegisterType(x);
}
}
有关调试信息,请参阅图像:
Jim Bolla感谢您的投入。这是我第一次尝试你的建议。
public class AssemblyLocator : IAssemblyLocator
{
public IList<Assembly> GetAssemblies()
{
var directoryName = HttpContext.Current.Server.MapPath("~/bin/");
var cfg = new ModularityLoader(new ModularityConfig(Path.Combine(directoryName, @"Modules")), new Log4NetLogger(typeof(ModularityConfig)));
return cfg.LoadedAssemblies;
}
}
还在Container = builder.Build上面添加了这个:
builder.RegisterType<AssemblyLocator>().As<IAssemblyLocator>().SingleInstance();
现在调用AssemblyLocator.GetAssemblies()。
......测试......
好。所以现在当我在javascript中抛出一个断点时,我可以看到$ .connection.BatchHub这很棒!但是,当尝试在服务器端调用hub方法RemoveBatchRow时,我收到以下错误:
“不支持使用HubPipeline未创建的Hub实例。”
这是堆栈跟踪:
在 Microsoft.AspNet.SignalR.Hubs.NullClientProxy.TryInvokeMember(InvokeMemberBinder binder,Object [] args,Object&amp;结果)在CallSite.Target(Closure, CallSite,Object,Guid)at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid2 [T0,T1](调用点 site,T0 arg0,T1 arg1)at KL.Apps.WebIndex.Hubs.BatchHub.RemoveBatchRow(Guid batchId)in d:\ Source \ Apps Framework Modules \ WebIndex \ Main \ Source \ KL.Apps.WebIndex \ Hubs \ BatchHub.cs:第20行 在 KL.Apps.WebIndex.API.Batch.BatchLockController.TryLockBatchAsync(字符串 batchId)在d:\ Source \ Apps Framework中 模块\ WebIndex \ MAIN \来源\ KL.Apps.WebIndex \ API \批次\ BatchLockController.cs:行 30在lambda_method(Closure,Object,Object [])at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor&LT;&GT; c__DisplayClass13.b__c(对象 instance,Object [] methodParameters)at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(对象 instance,Object [] arguments)at System.Web.Http.Controllers.ReflectedHttpActionDescriptor&LT;&GT; c__DisplayClass5.b__4() 在System.Threading.Tasks.TaskHelpers.RunSynchronously [TResult](Func`1 func,CancellationToken cancellationToken)
我从我的一个远程dll调用hub方法:
new BatchHub().RemoveBatchRow(gId);
您可以在上面看到BatchHub的定义。
还有其他想法吗?