C# 创建具有动态类型的泛型对象
我对C#中的泛型类型有问题。这是我的最小客户:C# 创建具有动态类型的泛型对象,c#,generics,C#,Generics,我对C#中的泛型类型有问题。这是我的最小客户: using Castle.DynamicProxy; using Newtonsoft.Json; using System; using System.Collections.Generic; using System.Linq; using System.Reactive.Disposables; using System.Reactive.Linq; using System.Reactive.Subjects; using System.T
using Castle.DynamicProxy;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text;
using System.Threading.Tasks;
namespace WebProxyClientTester
{
public class LiveResultPromise<R, L>
{
private Task<R> result;
private IObservable<L> notification;
public LiveResultPromise(Task<R> result, IObservable<L> notification)
{
this.result = result;
this.notification = notification;
}
public Task<R> Result { get => result; set => result = value; }
public IObservable<L> Notification { get => notification; set => notification = value; }
}
public class UserContact
{
public UserContact()
{
}
}
public class User
{
public User()
{
}
}
public class AddressBook
{
public AddressBook()
{
}
}
class Response<T>
{
private int id;
private T result;
private object error;
public int Id { get => id; set => id = value; }
public T Result { get => result; set => result = value; }
public object Error { get => error; set => error = value; }
}
public interface MyInterface
{
LiveResultPromise<UserContact, UserContact> getUserContact(String username);
LiveResultPromise<User, User> getUsers();
LiveResultPromise<AddressBook, AddressBook> getAddressBook();
}
class Client
{
Subject<Response<dynamic>> wsResponse = new Subject<Response<dynamic>>();
int id = 1;
public Client()
{
}
public Subject<Response<dynamic>> WsResponse { get => wsResponse; set => wsResponse = value; }
public dynamic Invoke(String methodName, object[] arguments, Type returnType)
{
TaskCompletionSource<dynamic> taskResult = new TaskCompletionSource<dynamic>();
IObservable<Response<dynamic>> notification = Observable.Create<Response<dynamic>>((result) =>
{
wsResponse.Subscribe((res) =>
{
if (id == res.Result)
{
result.OnNext(res.Result);
}
}, (error) => { });
return Disposable.Create(() => Console.WriteLine("Observer has unsubscribed"));
});
LiveResultPromise<dynamic, dynamic> liveResultPromise = new LiveResultPromise<dynamic, dynamic>(taskResult.Task, notification);
id++;
return liveResultPromise;
}
}
class ProxyUtils : IInterceptor
{
private Client client;
public ProxyUtils(Client client)
{
this.client = client;
}
public void Intercept(IInvocation invocation)
{
invocation.ReturnValue = client.Invoke(invocation.Method.Name, invocation.Arguments, invocation.Method.ReturnType);
}
}
class TestCLientExample
{
private static MyInterface requestClient;
static void Main(string[] args)
{
Client client = new Client();
requestClient = new ProxyGenerator().CreateInterfaceProxyWithoutTarget<MyInterface>(new ProxyUtils(client));
LiveResultPromise<User, User> users = requestClient.getUsers();
LiveResultPromise<UserContact, UserContact> contact = requestClient.getUserContact("pippo");
LiveResultPromise<AddressBook, AddressBook> addressBook = requestClient.getAddressBook();
users.Notification.Subscribe((result) =>
{
Console.WriteLine("User Object");
});
contact.Notification.Subscribe((result) =>
{
Console.WriteLine("UserContact Object");
});
addressBook.Notification.Subscribe((result) =>
{
Console.WriteLine("AddressBook Object");
});
Response<User> res1 = new Response<User>();
res1.Id = 1;
res1.Result = new User();
client.WsResponse.OnNext(res1);
Response<UserContact> res2 = new Response<UserContact>();
res2.Id = 2;
res2.Result = new UserContact();
client.WsResponse.OnNext(res2);
Response<AddressBook> res3 = new Response<AddressBook>();
res3.Id = 3;
res3.Result = new AddressBook();
client.WsResponse.OnNext(res3);
}
}
}
第二个问题是结果:
LiveResultPromise<User, User> users = requestClient.getUsers();
LiveResultPromise<UserContact, UserContact> contact = requestClient.getUserContact("pippo");
LiveResultPromise<AddressBook, AddressBook> addressBook = requestClient.getAddressBook();
LiveResultPromise-users=requestClient.getUsers();
LiveResultPromise contact=requestClient.getUserContact(“pippo”);
LiveResultPromise addressBook=requestClient.getAddressBook();
因为例如LiveResultPromise
无法强制转换为LiveResultPromise
我怎么能做类似的事情
谢谢。我已经用这个解决方案解决了我的问题
using Castle.DynamicProxy;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text;
using System.Threading.Tasks;
namespace WebProxyClientTester
{
public class LiveResultPromise<R, L>
{
private Task<R> result;
private IObservable<L> notification;
public LiveResultPromise(Task<R> result, IObservable<L> notification)
{
this.result = result;
this.notification = notification;
}
public Task<R> Result { get => result; set => result = value; }
public IObservable<L> Notification { get => notification; set => notification = value; }
}
public class UserContact
{
public UserContact()
{
}
}
public class User
{
public User()
{
}
}
public class AddressBook
{
public AddressBook()
{
}
}
class Response
{
private int id;
private dynamic result;
private object error;
public int Id { get => id; set => id = value; }
public dynamic Result { get => result; set => result = value; }
public object Error { get => error; set => error = value; }
}
class MutableInt
{
private int value;
public MutableInt(int value)
{
this.Value = value;
}
public int Value { get => value; set => this.value = value; }
public int GetAndIncrement()
{
int last = Value;
Value++;
return last;
}
}
public interface MyInterface
{
LiveResultPromise<UserContact, UserContact> getUserContact(String username);
LiveResultPromise<User, User> getUsers();
LiveResultPromise<AddressBook, AddressBook> getAddressBook();
}
class Client
{
Subject<Response> wsResponse = new Subject<Response>();
MutableInt idRequest = new MutableInt(1);
public Client()
{
}
public Subject<Response> WsResponse { get => wsResponse; set => wsResponse = value; }
public dynamic Invoke<T, R>(String methodName, object[] arguments, Type returnType, T typeResult, R typeNotify)
{
int currentId = idRequest.GetAndIncrement();
TaskCompletionSource<T> taskResult = new TaskCompletionSource<T>();
IObservable<R> notification = Observable.Create<R>((result) =>
{
wsResponse.Subscribe((res) =>
{
if (currentId == res.Id)
{
result.OnNext(res.Result);
}
}, (error) => { });
return Disposable.Create(() => Console.WriteLine("Observer has unsubscribed"));
});
LiveResultPromise<T, R> liveResultPromise = new LiveResultPromise<T, R>(taskResult.Task, notification);
return liveResultPromise;
}
}
class ProxyUtils : IInterceptor
{
private Client client;
public ProxyUtils(Client client)
{
this.client = client;
}
public void Intercept(IInvocation invocation)
{
System.Type genericType = invocation.Method.ReturnType;
dynamic typeResult = null;
dynamic typeNotify = null;
if (genericType.GetGenericArguments().Length > 0)
{
if (genericType.GetGenericArguments().Length >= 1)
{
typeResult = genericType.GetGenericArguments()[0];
}
if (genericType.GetGenericArguments().Length >= 2)
{
typeNotify = genericType.GetGenericArguments()[1];
}
}
var result = Activator.CreateInstance(typeResult);
var notification = Activator.CreateInstance(typeNotify);
invocation.ReturnValue = client.Invoke(invocation.Method.Name, invocation.Arguments, invocation.Method.ReturnType, result, notification);
}
}
class TestCLientExample
{
private static MyInterface requestClient;
static void Main(string[] args)
{
Client client = new Client();
requestClient = new ProxyGenerator().CreateInterfaceProxyWithoutTarget<MyInterface>(new ProxyUtils(client));
LiveResultPromise<User, User> users = requestClient.getUsers();
LiveResultPromise<UserContact, UserContact> contact = requestClient.getUserContact("pippo");
LiveResultPromise<AddressBook, AddressBook> addressBook = requestClient.getAddressBook();
users.Notification.Subscribe((result) =>
{
Console.WriteLine("User Object");
});
contact.Notification.Subscribe((result) =>
{
Console.WriteLine("UserContact Object");
});
addressBook.Notification.Subscribe((result) =>
{
Console.WriteLine("AddressBook Object");
});
Response res1 = new Response();
res1.Id = 1;
res1.Result = new User();
client.WsResponse.OnNext(res1);
Response res2 = new Response();
res2.Id = 2;
res2.Result = new UserContact();
client.WsResponse.OnNext(res2);
Response res3 = new Response();
res3.Id = 3;
res3.Result = new AddressBook();
client.WsResponse.OnNext(res3);
}
}
}
如果你知道更好的解决办法,请告诉我
谢谢。@HimBromBeere我认为这不是一个好的复制品。OP希望更改所创建的类型。但是,我认为问题是XY或者需要进行重构以完全不需要它。您是否可以将
Invoke
也设置为泛型,而不是传入类型?或者是动态创建的类型(意味着您在编译时不知道它)@DavidG如果解决方案是“使用反射构造方法调用”,那么它是重复的,但这是一个假设,我同意可能有更好的解决方案。另外,为什么您要使用Invoke
?你没有使用methodName
和参数
参数,所以我不明白你为什么需要在Invoke
@D中包装调用Stanley我已经用Invoke类更新了我的帖子,我不知道编译时的类型。
LiveResultPromise<User, User> users = requestClient.getUsers();
LiveResultPromise<UserContact, UserContact> contact = requestClient.getUserContact("pippo");
LiveResultPromise<AddressBook, AddressBook> addressBook = requestClient.getAddressBook();
using Castle.DynamicProxy;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
using System.Text;
using System.Threading.Tasks;
namespace WebProxyClientTester
{
public class LiveResultPromise<R, L>
{
private Task<R> result;
private IObservable<L> notification;
public LiveResultPromise(Task<R> result, IObservable<L> notification)
{
this.result = result;
this.notification = notification;
}
public Task<R> Result { get => result; set => result = value; }
public IObservable<L> Notification { get => notification; set => notification = value; }
}
public class UserContact
{
public UserContact()
{
}
}
public class User
{
public User()
{
}
}
public class AddressBook
{
public AddressBook()
{
}
}
class Response
{
private int id;
private dynamic result;
private object error;
public int Id { get => id; set => id = value; }
public dynamic Result { get => result; set => result = value; }
public object Error { get => error; set => error = value; }
}
class MutableInt
{
private int value;
public MutableInt(int value)
{
this.Value = value;
}
public int Value { get => value; set => this.value = value; }
public int GetAndIncrement()
{
int last = Value;
Value++;
return last;
}
}
public interface MyInterface
{
LiveResultPromise<UserContact, UserContact> getUserContact(String username);
LiveResultPromise<User, User> getUsers();
LiveResultPromise<AddressBook, AddressBook> getAddressBook();
}
class Client
{
Subject<Response> wsResponse = new Subject<Response>();
MutableInt idRequest = new MutableInt(1);
public Client()
{
}
public Subject<Response> WsResponse { get => wsResponse; set => wsResponse = value; }
public dynamic Invoke<T, R>(String methodName, object[] arguments, Type returnType, T typeResult, R typeNotify)
{
int currentId = idRequest.GetAndIncrement();
TaskCompletionSource<T> taskResult = new TaskCompletionSource<T>();
IObservable<R> notification = Observable.Create<R>((result) =>
{
wsResponse.Subscribe((res) =>
{
if (currentId == res.Id)
{
result.OnNext(res.Result);
}
}, (error) => { });
return Disposable.Create(() => Console.WriteLine("Observer has unsubscribed"));
});
LiveResultPromise<T, R> liveResultPromise = new LiveResultPromise<T, R>(taskResult.Task, notification);
return liveResultPromise;
}
}
class ProxyUtils : IInterceptor
{
private Client client;
public ProxyUtils(Client client)
{
this.client = client;
}
public void Intercept(IInvocation invocation)
{
System.Type genericType = invocation.Method.ReturnType;
dynamic typeResult = null;
dynamic typeNotify = null;
if (genericType.GetGenericArguments().Length > 0)
{
if (genericType.GetGenericArguments().Length >= 1)
{
typeResult = genericType.GetGenericArguments()[0];
}
if (genericType.GetGenericArguments().Length >= 2)
{
typeNotify = genericType.GetGenericArguments()[1];
}
}
var result = Activator.CreateInstance(typeResult);
var notification = Activator.CreateInstance(typeNotify);
invocation.ReturnValue = client.Invoke(invocation.Method.Name, invocation.Arguments, invocation.Method.ReturnType, result, notification);
}
}
class TestCLientExample
{
private static MyInterface requestClient;
static void Main(string[] args)
{
Client client = new Client();
requestClient = new ProxyGenerator().CreateInterfaceProxyWithoutTarget<MyInterface>(new ProxyUtils(client));
LiveResultPromise<User, User> users = requestClient.getUsers();
LiveResultPromise<UserContact, UserContact> contact = requestClient.getUserContact("pippo");
LiveResultPromise<AddressBook, AddressBook> addressBook = requestClient.getAddressBook();
users.Notification.Subscribe((result) =>
{
Console.WriteLine("User Object");
});
contact.Notification.Subscribe((result) =>
{
Console.WriteLine("UserContact Object");
});
addressBook.Notification.Subscribe((result) =>
{
Console.WriteLine("AddressBook Object");
});
Response res1 = new Response();
res1.Id = 1;
res1.Result = new User();
client.WsResponse.OnNext(res1);
Response res2 = new Response();
res2.Id = 2;
res2.Result = new UserContact();
client.WsResponse.OnNext(res2);
Response res3 = new Response();
res3.Id = 3;
res3.Result = new AddressBook();
client.WsResponse.OnNext(res3);
}
}
}
var result = Activator.CreateInstance(typeResult);
var notification = Activator.CreateInstance(typeNotify);