具有通用服务的服务结构
我希望有一个通用类型的服务,即 –
public interface IFooService { Task Get(int id); }
但是,服务结构不允许generics类或generics方法。 我也尝试过类似的东西
public interface INinjaService : IService, IFooService { }
但它没有选择inheritance的接口说明
服务类型“Omni.Fabric.Services.NinjaService”未实现任何服务接口。 服务接口是从“Microsoft.ServiceFabric.Services.Remoting.IService”类型派生的接口。
我似乎无法在Service Fabric文档或stackoverflow上找到任何关于generics的引用。 要么它仍然太新,要么我可能走错了路。 有没有人有幸实现这种模式? 可以吗? 它应该完成吗?
NinjaService按要求提供
public class NinjaService : StatelessService, INinjaService { public NinjaService(StatelessServiceContext serviceContext) : base(serviceContext) { } protected override IEnumerable CreateServiceInstanceListeners() { return new[] { new ServiceInstanceListener(context => this.CreateServiceRemotingListener(context)) }; } public Task Get(int id) { return Task.FromResult(new SuperNinja()); } }
消耗代码(从Owin WebApi服务调用
public async Task Get(int key) { try { INinjaService service = ServiceProxy.Create(new Uri("fabric:/Omni.Fabric/Services")); var t = await service.Get(key).ConfigureAwait(false); return t; } catch (Exception ex) { throw; } }
Service Fabric中的服务可以实现通用接口:
interface IMyService { T Foo(); } class Stateful1 : StatefulService, IMyService { public Stateful1(StatefulServiceContext context) : base(context) { } public string Foo() { // do foo } }
这可以。
不支持的是远程过程调用(RPC)的通用接口。 这特定于Service Remoting通信堆栈,这是您使用IService和Remoting通信监听器所拥有的。
所以在你的情况下,不,还没有支持generics。 但这是特定服务通信堆栈的限制,而不是一般服务的限制,当然您可以使用任何所需的通信堆栈 。
Service Fabric正在使用此扩展方法来删除非服务类型接口
internal static class ServiceTypeExtensions { public static Type[] GetServiceInterfaces(this Type serviceType) { List typeList = new List (((IEnumerable )serviceType.GetInterfaces()).Where(t => typeof(IService).IsAssignableFrom(t))); typeList.RemoveAll(t => t.GetNonServiceParentType() != null); return typeList.ToArray(); } internal static Type GetNonServiceParentType(this Type type) { List typeList = new List (type.GetInterfaces()); if (typeList.RemoveAll(t => t == typeof(IService)) == 0) return type; foreach (Type type1 in typeList) { Type serviceParentType = type1.GetNonServiceParentType(); if (serviceParentType != null) return serviceParentType; } return null; } }
并检查结果
if (serviceInterfaces.Length == 0 && !serviceType.IsAbstract) throws the exception in question
所以我找到了解决此案例的方法
public interface IServiceWrapper : IService { } public interface INinjaService : IServiceWrapper, IFooService { }
更新
经过一番调查后,我发现代理正在检查所有接口父母是否需要IService,这意味着
Type serviceParentType = serviceInterfaceType.GetNonServiceParentType(); if (serviceParentType != null) throws another exception
所以你需要从IService
派生IFooService
,目前不支持。
因此不支持generics:(
这个答案可能会迟到,但它可能对某人有所帮助。 我通过确保服务类中实现的每个接口都inheritance自IService来解决这个问题。 在你的情况下,你有以下内容:
public interface IFooService : IService { Task Get(int id); } public interface INinjaService : IFooService { } public class NinjaService : StatelessService, INinjaService { }
试试吧,它应该工作。 如果您需要在服务中实现多个接口,我已尝试以下选项:
public interface MyInterfaceA : IService { } public interface MyInterfaceB : IService { } public class MyServiceAB : StatelessService, MyInterfaceA, MyInterfaceB { }
要么
public interface MyInterfaceA : IService { } public interface MyInterfaceB : IService { } public interface MyInterfaceC : MyInterfaceA, MyInterfaaceB { } public class MyServiceC : StatelessService, MyInterfaceC { }
希望有所帮助。
由于我想从一个服务到另一个服务进行调用,我所做的解决方法是传递一个带有Type名称的字符串,并用reflection调用另一个方法。
public async Task GetResultAsync(Site site, string indexableType, SearchQuery searchQuery) { using (var provider = new Provider(Logger)) { var indexableT = typeof(IIndexable).Assembly .GetTypes() .FirstOrDefault(t => typeof(IIndexable).IsAssignableFrom(t) && t.Name == indexableType); if (indexableT != null) { var generic = provider .GetType() .GetMethod("METHOD_NAME_IN_PROVIDER")) .MakeGenericMethod(indexableT); //This is the same as calling: await provider.METHOD_NAME_IN_PROVIDER(site, searchQuery); return await (Task) generic.Invoke(provider, new object[] { site, searchQuery }); } return null; } }
希望它可以帮到某人。