WCF サービスで依存性注入に Unity を使用する方法を探していました。私はこれら 2 つのブログで説明されているコードを理解しようとしていますが、これは非常によく似ています。
そこで、このコードをソリューションの別のプロジェクトに追加し、SVC ファイルのカスタム servicehostfactory を WFC サービス (別のプロジェクト) に参照させました。
問題は、WCF サービス メソッドからコンテナー内のオブジェクトにアクセスするにはどうすればよいかということです。
編集
これらは私の実装です:
ServiceHostFactory...
namespace UnityWcfAssembler
{
public class UnityServiceHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
UnityServiceHost serviceHost = new UnityServiceHost(serviceType, baseAddresses);
UnityContainer container = new UnityContainer();
serviceHost.Container = container;
//TODO configuration from app.config
//configure container
//UnityConfigurationSection section = (UnityConfigurationSection)ConfigurationManager.GetSection("unity");
//section.Configure(serviceHost.Container);
InitializeSessionFactories(container);
return serviceHost;
}
private static void InitializeSessionFactories(UnityContainer container)
{
Dictionary<String, ISessionFactory> sessions = new Dictionary<string, ISessionFactory>();
Configuration Cfg = new Configuration();
Cfg.Configure();
Cfg.SetProperty("connection.connection_string",
"Data Source=(Local);Initial Catalog=Fossils;Integrated Security=true;");
ISessionFactory Factory = Cfg.BuildSessionFactory();
sessions.Add("fossils", Factory);
Cfg.SetProperty("connection.connection_string",
"Data Source=(Local);Initial Catalog=TypeCollection;Integrated Security=true;");
ISessionFactory typeFactory = Cfg.BuildSessionFactory();
sessions.Add("type", typeFactory);
Cfg.SetProperty("connection.connection_string",
"Data Source=(Local);Initial Catalog=PersonalCollection;Integrated Security=true;");
ISessionFactory persFactory = Cfg.BuildSessionFactory();
sessions.Add("personal", persFactory);
container.RegisterInstance(sessions);
}
}
}
サービスホスト...
namespace UnityWcfAssembler
{
public class UnityServiceHost : ServiceHost
{
public UnityContainer Container { get; set; }
public UnityServiceHost()
{
Container = new UnityContainer();
}
public UnityServiceHost(Type serviceType, params Uri[] baseAddresses) : base(serviceType, baseAddresses)
{
Container = new UnityContainer();
}
protected override void OnOpening()
{
new UnityServiceBehavior(Container).AddToHost(this);
base.OnOpening();
if (Description.Behaviors.Find<UnityServiceBehavior>() == null)
Description.Behaviors.Add(new UnityServiceBehavior(Container));
}
}
}
インスタンスプロバイダー...
namespace UnityWcfAssembler
{
public class UnityInstanceProvider : IInstanceProvider
{
public UnityContainer Container { set; get; }
public Type ServiceType { set; get; }
public UnityInstanceProvider() : this(null)
{
}
public UnityInstanceProvider(Type type)
{
ServiceType = type;
Container = new UnityContainer();
}
// Get Service instace via unity container
public object GetInstance(InstanceContext instanceContext, Message message)
{
return Container.Resolve(ServiceType);
}
public object GetInstance(InstanceContext instanceContext)
{
return GetInstance(instanceContext, null);
}
public void ReleaseInstance(InstanceContext instanceContext, object instance)
{
}
}
}
IServiceBehavior...
namespace UnityWcfAssembler
{
public class UnityServiceBehavior : IServiceBehavior
{
public UnityInstanceProvider InstanceProvider { get; set; }
private ServiceHost serviceHost;
public UnityServiceBehavior()
{
InstanceProvider = new UnityInstanceProvider();
}
public UnityServiceBehavior(UnityContainer unity)
{
InstanceProvider = new UnityInstanceProvider();
InstanceProvider.Container = unity;
}
public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ChannelDispatcherBase cdb in serviceHostBase.ChannelDispatchers)
{
ChannelDispatcher cd = cdb as ChannelDispatcher;
if (cd != null)
{
foreach (EndpointDispatcher ed in cd.Endpoints)
{
InstanceProvider.ServiceType = serviceDescription.ServiceType;
ed.DispatchRuntime.InstanceProvider = InstanceProvider;
}
}
}
}
public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters) { }
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase) { }
public void AddToHost(ServiceHost host)
{
// only add to host once
if (serviceHost != null) return;
host.Description.Behaviors.Add(this);
serviceHost = host;
}
}
}
Wcf サービス...
namespace FossilsWcfService
{
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class FossilsService : IFossilsService
{
private readonly Dictionary<string, ISessionFactory> sessionFactories;
public FossilsService(Dictionary<string, ISessionFactory> s)
{
sessionFactories = s;
}
public SpeciesList GetAllSpecies()
{
SpeciesList list = new SpeciesList();
ISessionFactory factory = sessionFactories["fossils"];
if(factory == null)
{
list.Species.Add(new FossilSpecies { GenusName = "Session factory could not be resolved from container!" });
return list;
}
ISession session = factory.OpenSession();
SpeciesManager speciesManager = new SpeciesManager(session);
IList<FossilSpecies> species = speciesManager.GetAllSpecies();
foreach (FossilSpecies fossilSpecies in species)
{
list.Species.Add(fossilSpecies);
}
return list;
}
FossilsWcfService.svc...
<%@ ServiceHost Language="C#" Debug="true"
Service="Server.Services.ExampleService"
Factory="UnityWcfAssembler.UnityServiceHostFactory" %>
後者にはおそらく別のファイル名が必要ですか?