我有一个客户端 - 服务器应用程序,它通过WCF进行相互通信。他们还使用Castle Windsor来解决依赖关系。
我的目标是完全避免必须显式注册服务器或客户端WCF端点。 我使用以下代码
通过'约定'实现了服务器端// registers all services which implement exactly 1 [ServiceContract]
_windsorContainer.Register(
AllTypes.FromThisAssembly().IncludeNonPublicTypes().Where(
t => 1 == (from i in t.GetInterfaces() where i.IsDefined(typeof(ServiceContractAttribute), true) select i).Count())
.Configure(c => c.LifeStyle.PerWcfSession()
.ActAs(new DefaultServiceModel().AddEndpoints(
WcfEndpoint.BoundTo(new NetTcpBinding())
.At("net.tcp://" + LocalAddress.ToString() + ":7601/" + c.ServiceType.Name),
WcfEndpoint.FromEndpoint(new UdpDiscoveryEndpoint())
))
).WithService.Select(
(Type type, Type[] baseTypes) => from i in type.GetInterfaces() where i.IsDefined(typeof(ServiceContractAttribute), true) select i
)
);
此代码将查找当前程序集中的所有类,并且任何实现服务契约接口(由ServiceContract属性标识)的类都将在地址“net.tcp:// localhost”中注册(使用UDP发现): 7601 / [服务合同接口名称]”。
现在,我只想要方程式的客户端。
通常,要使用castle为WCF合同生成客户端代理,以下代码将起作用:
var model = new DefaultClientModel
{
Endpoint = WcfEndpoint.ForContract<IServiceContract>().BoundTo(new NetTcpBinding()).Discover(typeof(IServiceContract))
};
container.Register(
Component.For<ChannelReconnectPolicy>(),
Castle.Facilities.WcfIntegration.WcfClient.ForChannels(model),
);
我想要的是,Castle为给定程序集中的所有“服务契约”接口执行此类注册 - 但是AllTypes帮助程序似乎只返回类,而不是接口(我猜它是'AllClasses ',而不是'AllTypes'!)... Can Castle可以做到这一点,语法是什么?克日什托夫? (帮助!)
谢谢!
答案 0 :(得分:1)
对这样一个迟到的回复道歉 - 开发人员的生活从来都不是一个安静的人!
我挖出了代码,并没有像我希望的那样“简洁”,也许有人可以将这样的东西整合到Castle中......但是这里有......
// these are all the namespaces that will be scanned for WCF service contracts
string[] remoteServiceNamespaces
= new string[] { "MyContracts.Services", "Interlinq" };
// everything from here on is in the Castle DLLs (all the types)
List<IRegistration> clientContractRegistrations = new List<IRegistration>();
foreach (
var interfaceContract in
(from s in remoteServiceNamespaces
select (from i in Assembly.LoadWithPartialName(s).GetTypes()
where i.IsInterface
&&
i.IsDefined(typeof(ServiceContractAttribute), false)
select i)).SelectMany( x => x )
)
{
ServiceContractAttribute attr
= Attribute.GetCustomAttribute(
interfaceContract,
typeof(ServiceContractAttribute))
as ServiceContractAttribute;
if (null != attr)
{
WcfClientModelBase model = null;
// here we handle the case of the service being duplex...
if (null != attr.CallbackContract)
{
model = new DuplexClientModel
{
// All the automatically registered services will use NetTcp,
// and will discover their addresses (you could use binding
// inference aswell if you liked)
// here I have a method called 'CreateNetTcpBinding' which
// creates my custom binding that ALL my services use.
Endpoint =
WcfEndpoint.ForContract(interfaceContract)
.BoundTo(CreateNetTcpBinding())
.Discover(interfaceContract)
.PreferEndpoint(list => list[0])
}.Callback(_windsor.Resolve(attr.CallbackContract));
}
else
{
model = new DefaultClientModel
{
Endpoint = WcfEndpoint.ForContract(interfaceContract)
.BoundTo(new NetTcpBinding())
.Discover(interfaceContract)
.PreferEndpoint(list => list[0])
};
}
clientContractRegistrations.Add(WcfClient.ForChannels(model));
}
}
// now that we've built our registration list, let's actually register
// them all with Windsor
_windsor.Register(
clientContractRegistrations.ToArray()
);