Pet*_*ter 5 c# wcf ioc-container
我正在尝试向我的REST WCF服务(Windows Server 2008)添加IoC支持.我是新手,并且遵循以下视频中提供的说明:
http://www.dimecasts.net/Content/WatchEpisode/150
该视频介绍了许多类,这些类可以帮助我在暴露WCF端点的同时启动和运行StructureMap的IoC.我在本文末尾发布了所有代码.
当我运行我的代码时,自定义类StructureMapServiceHost会抛出一个错误@ StructureMapServiceHost(类型serviceType,params Uri [] baseAddress)方法:
public class StructureMapServiceHost : ServiceHost
{
public StructureMapServiceHost() {}
public StructureMapServiceHost(Type serviceType, params Uri[] baseAddress)
: base(serviceType, baseAddress)
{
}
protected override void OnOpening()
{
Description.Behaviors.Add( new IoCServiceBehavior());
base.OnOpening();
}
}
Run Code Online (Sandbox Code Playgroud)
我被告知:
提供的服务类型无法作为服务加载,因为它没有默认(无参数)构造函数.要解决此问题,请为该类型添加默认构造函数,或将该类型的实例传递给主机.
这是事实,但事实并非如此.但视频示例也没有.以下是我的服务:
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class UserService : IUserService
{
public UserService(IUserRepository specification)
{
Specification = specification;
}
public List<User> GetAllUsers()
{
return Specification.GetAllUsers();
}
public User GetUser(string userId)
{
return Specification.GetUserById(new Guid(userId));
}
private List<User> SearchForUsers(string searchString)
{
return Specification.SearchUsers(searchString);
}
public IUserRepository Specification { get; set; }
}
public class IoCServiceBehavior : IServiceBehavior
{
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase,
Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
{
new StructureMapInstanceProvider(serviceDescription.ServiceType);
}
}
}
public class StructureMapInstanceProvider : IInstanceProvider
{
private readonly Type _serviceType;
public StructureMapInstanceProvider(Type serviceType)
{
_serviceType = serviceType;
}
public object GetInstance(InstanceContext instanceContext)
{
return GetInstance(instanceContext, null);
}
public object GetInstance(InstanceContext instanceContext, Message message)
{
var instance = ObjectFactory.GetInstance(_serviceType);
return instance;
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
throw new NotImplementedException();
}
}
public class StructureMapServiceHostFactory : ServiceHostFactory
{
public StructureMapServiceHostFactory()
{
IoCBootstrap.SetupIoc();
}
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
return new StructureMapServiceHost(serviceType, baseAddresses);
}
}
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?谢谢.
编辑********************************
从StructureMapServiceHost我删除:
public StructureMapServiceHost(Type serviceType, params Uri[] baseAddress)
: base(serviceType, baseAddress) { }
Run Code Online (Sandbox Code Playgroud)
并补充说:
public StructureMapServiceHost(Object singletonInstance, params Uri[] baseAddress)
: base( singletonInstance, baseAddress) { }
Run Code Online (Sandbox Code Playgroud)
然后从我的UserService构造函数中删除参数.我没有收到错误:
HTML文档不包含Web服务发现信息.
Nea*_*eal 17
您的服务使用InstanceContextMode.SingleCall,WCF团队以其无限的智慧决定,当InstanceContextMode为SingleCall时,不会调用IInstanceProvider来创建实例(请参阅http://blogs.msdn.com/b/carlosfigueira/archive /2011/05/31/wcf-extensibility-iinstanceprovider.aspx - 接口declration标题下面的第二个参数).
当然,我有一种不太理想的方式在服务主机工厂中解决这个问题:
using System;
using System.Collections.Generic;
using System.ServiceModel;
using System.ServiceModel.Activation;
using StructureMap;
using StructureMap.Pipeline;
using System.Linq;
using ServiceHostCreator = System.Func<System.Type, System.Uri[], System.ServiceModel.ServiceHost>;
namespace x.ServiceExtensions
{
public class xWebServiceHostFactory : ServiceHostFactory
{
private readonly IDictionary<InstanceContextMode, ServiceHostCreator> _serviceHostCreators;
public xWebServiceHostFactory()
{
ObjectFactory.Initialize( init =>
init.Scan( scan =>
{
scan.AssembliesFromApplicationBaseDirectory();
scan.IgnoreStructureMapAttributes();
scan.LookForRegistries();
} ) );
_serviceHostCreators = new Dictionary<InstanceContextMode, ServiceHostCreator>
{
{ InstanceContextMode.PerCall, ( t, a ) => PerCallServiceHostCreator( t, a ) },
{ InstanceContextMode.PerSession, ( t, a ) => PerSessionServiceHostCreator( t, a ) },
{ InstanceContextMode.Single, ( t, a ) => SingleInstanceServiceHostCreator( t, a ) }
};
}
protected override ServiceHost CreateServiceHost( Type serviceType, Uri[] baseAddresses )
{
var serviceInstanceContextMode = GetServiceInstanceContextMode( serviceType );
var serviceHostCreator = _serviceHostCreators[ serviceInstanceContextMode ];
return serviceHostCreator( serviceType, baseAddresses );
}
private static InstanceContextMode GetServiceInstanceContextMode( Type serviceType )
{
var serviceBehaviour = serviceType
.GetCustomAttributes( typeof ( ServiceBehaviorAttribute ), true )
.Cast<ServiceBehaviorAttribute>()
.SingleOrDefault();
return serviceBehaviour.InstanceContextMode;
}
private static ServiceHost PerCallServiceHostCreator( Type serviceType, Uri[] baseAddresses )
{
var args = new ExplicitArguments();
args.Set( serviceType );
args.Set( baseAddresses );
var serviceHost = ObjectFactory.GetInstance<TelaWebServiceHost>( args );
return serviceHost;
}
private static ServiceHost PerSessionServiceHostCreator( Type serviceType, Uri[] baseAddresses )
{
return PerCallServiceHostCreator( serviceType, baseAddresses );
}
private static ServiceHost SingleInstanceServiceHostCreator( Type serviceType, Uri[] baseAddresses )
{
var service = ObjectFactory.GetInstance( serviceType );
var args = new ExplicitArguments();
args.Set( typeof(object), service );
args.Set( baseAddresses );
var serviceHost = ObjectFactory.GetInstance<TelaWebServiceHost>( args );
return serviceHost;
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是一项正在进行的工作,可能有更好的方法,但目前我找不到一个.
我现在无法观看视频(互联网限制),但我很确定他们示例中的类根本没有任何构造函数。在这种情况下,编译器会代表您生成一个空的无参数构造函数。因此,他们的类毕竟有一个默认的构造函数。
就例外而言,这似乎非常简单:您的无参数构造函数不会初始化该Specification属性,因此它总是如此-一旦您尝试在方法中访问它null,这自然会导致 a 。NullReferenceException
看来您在这里的目的是UserService自己创建对象并将 a 传递IUserRepository给它,不是吗?(或者,也许,使用你的 IoC 框架?)
在这种情况下,您最好使用 的ServiceHost构造函数的重载,该构造函数采用 anobject而不是Type。这样,您将完全控制您的UserService对象,并且根本不需要默认构造函数。
| 归档时间: |
|
| 查看次数: |
8435 次 |
| 最近记录: |