【发布时间】:2017-05-15 14:46:46
【问题描述】:
我知道关于这个主题有很多有答案和没有答案的问题,但似乎没有一个与我的问题完全匹配。
我正在尝试为我的项目实体编写管理器服务。对于主要的、大的和重要的,我已经完成了,但是业务包含很多描述符(只有 ID 和名称的实体,其他实体使用),我也希望能够将它们作为服务进行管理。
一种解决方案是为它们中的每一个设置一个特定的管理器,但由于描述符的数量,这肯定会破坏可维护性。于是我写了2个接口如下
public interface IIdentifiableEntity
{
string EntityId { get; set; }
}
public interface IDescriptorEntity: IIdentifiableEntity
{
string EntityDesc { get; set; }
}
这是由于我的主要实体实现了 IIdentifiableEntity 而我的描述符实现了 IDescriptorEntity
这是我的描述符实体之一的示例:
public class JobCode: IDescriptorEntity
{
[DataMember]
public string JobCodeID { get; set; }
[DataMember]
public string JobCodeDesc { get; set; }
public string EntityId
{
get
{
return JobCodeID;
}
set
{
JobCodeID = value;
}
}
public string EntityDesc
{
get
{
return JobCodeDesc;
}
set
{
JobCodeDesc = value;
}
}
}
然后我写了我的服务合同如下:
public interface IDescriptorService : IServiceContract
{
[OperationContract]
[FaultContract(typeof(NotFoundException))]
T Get<T>(string id) where T : class, IDescriptorEntity, new();
[OperationContract]
T[] GetAll<T>() where T : class, IDescriptorEntity, new();
[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
T Add<T>(T descriptor) where T : class, IDescriptorEntity, new();
[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
T Update<T>(T descriptor) where T : class, IDescriptorEntity, new();
[OperationContract]
[TransactionFlow(TransactionFlowOption.Allowed)]
void Delete<T>(string id) where T : class, IDescriptorEntity, new();
}
和我的经理(服务本身)如下:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall,
ConcurrencyMode = ConcurrencyMode.Multiple,
ReleaseServiceInstanceOnTransactionComplete = false)]
[Export(typeof(IDescriptorService))]
public class DescriptorManager : ManagerBase, IDescriptorService
{
public DescriptorManager()
{
ObjectBase.Container.SatisfyImportsOnce(this);
}
#region No MEF Discovery constructors
public DescriptorManager(IDataRepositoryFactory dataRepositoryFactory)
{
_DataRepositoryFactory = dataRepositoryFactory;
}
#endregion
[Import]
IDataRepositoryFactory _DataRepositoryFactory;
[PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
public TEntityType Get<TEntityType>(string id) where TEntityType : class, IDescriptorEntity, new() => ExecuteFaultHandledOperation(() =>
{
IDataRepository<TEntityType> repository = _DataRepositoryFactory.GetDataRepositoryOf<TEntityType>();
TEntityType entity = repository.Get(id);
if (entity == null)
{
NotFoundException ex
= new NotFoundException(string.Format("{0} with ID of {1} is not in the database", typeof(TEntityType).Name, id));
throw new FaultException<NotFoundException>(ex, ex.Message);
}
return entity;
});
[PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
public TEntityType[] GetAll<TEntityType>() where TEntityType : class, IDescriptorEntity, new() => ExecuteFaultHandledOperation(() =>
{
IDataRepository<TEntityType> repository = _DataRepositoryFactory.GetDataRepositoryOf<TEntityType>();
IEnumerable<TEntityType> entities = repository.Get();
return entities.ToArray();
});
[OperationBehavior(TransactionScopeRequired = true)]
[PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
public TEntityType Update<TEntityType>(TEntityType entity) where TEntityType : class, IDescriptorEntity, new() => ExecuteFaultHandledOperation(() =>
{
IDataRepository<TEntityType> repository = _DataRepositoryFactory.GetDataRepositoryOf<TEntityType>();
TEntityType updatedEntity = repository.Update(entity);
return updatedEntity;
});
[OperationBehavior(TransactionScopeRequired = true)]
[PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
public TEntityType Add<TEntityType>(TEntityType entity) where TEntityType : class, IDescriptorEntity, new() => ExecuteFaultHandledOperation(() =>
{
IDataRepository<TEntityType> repository = _DataRepositoryFactory.GetDataRepositoryOf<TEntityType>();
TEntityType updatedEntity = repository.Add(entity);
return updatedEntity;
});
[OperationBehavior(TransactionScopeRequired = true)]
[PrincipalPermission(SecurityAction.Demand, Authenticated = true)]
public void Delete<TEntityType>(string id) where TEntityType : class, IDescriptorEntity, new() => ExecuteFaultHandledOperation(() =>
{
IDataRepository<TEntityType> repository = _DataRepositoryFactory.GetDataRepositoryOf<TEntityType>();
repository.Remove(id);
});
}
并将托管应用程序作为控制台应用程序如下:
class Program
{
static void Main(string[] args)
{
ObjectBase.Container = MEFLoader.Init();
Console.WriteLine("Starting up services...");
Console.WriteLine("");
SM.ServiceHost hostDescriptorManager = new SM.ServiceHost(typeof(DescriptorManager));
SM.ServiceHost hostPositionManager = new SM.ServiceHost(typeof(PositionManager));
SM.ServiceHost hostEmployeeManager = new SM.ServiceHost(typeof(EmployeeManager));
StartService(hostDescriptorManager, "DescriptorManager");
StartService(hostPositionManager, "PositionManager");
StartService(hostEmployeeManager, "EmployeeManager");
Console.WriteLine("");
Console.WriteLine("Press [Enter] to exit.");
Console.ReadLine();
StopService(hostDescriptorManager, "DescriptorManager");
StopService(hostPositionManager, "PositionManager");
StopService(hostEmployeeManager, "EmployeeManager");
}
static void StartService(SM.ServiceHost host, string serviceDescription)
{
host.Open();
Console.WriteLine("Service {0} started", serviceDescription);
foreach (var endpoint in host.Description.Endpoints)
{
Console.WriteLine("Listening on endpoints:");
Console.WriteLine("Adress: {0}", endpoint.Address.Uri);
Console.WriteLine("Binding: {0}", endpoint.Binding.Name);
Console.WriteLine("Contract: {0}", endpoint.Contract.Name);
}
Console.WriteLine();
}
static void StopService(SM.ServiceHost host, string serviceDescription)
{
host.Close();
Console.WriteLine("Service {0} stopped.", serviceDescription);
}
}
我还想要一些组合和 DI(我正在使用 MEF 组合整个应用程序),因此我将我的实体(包括描述符)放在我加载的单独程序集中。因此,在我的类和接口中直接硬编码“KnownType”是行不通的。
所以我尝试关注this example from MSDN 并将已知类型写入配置文件(我可以稍后更改以保持我的组合)。在我尝试将 JobCode 描述符添加为 KnownType 的部分配置之后。
<system.runtime.serialization>
<dataContractSerializer>
<declaredTypes>
<add type="Core.Common.Contracts.IDescriptorEntity,Core.Common.Contracts">
<knownType type="XXXX.Business.Entities.JobCode,XXXX.Business.Entities"/>
</add>
</declaredTypes>
</dataContractSerializer>
然而,当我尝试运行主机时,在 IDescriptorService 接口的第一个方法中再次出现“Open Generics”错误。
我做错了什么?
【问题讨论】:
标签: c# entity-framework wcf generics