代码之家  ›  专栏  ›  技术社区  ›  Mattia

创建具有动态类型的泛型对象

  •  0
  • Mattia  · 技术社区  · 6 年前

    我对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.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);
            }
        }
    }
    

    我的代码有两个问题,第一部分

     Response<User> res1 = new Response<User>();
     res1.Id = 1;
     res1.Result = new User();
    
     client.WsResponse.OnNext(res1);
    

    灯塔 client.WsResponse 希望 Response<dynamic> 但是我把 Response<User> 编译器失败,出现错误:无法转换 响应<用户> 响应<动态> .

    我可以用这部分代码解决:

    Response<dynamic> res1 = new Response<dynamic>();
    res1.Id = 1;
    res1.Result = new User();
    
    client.WsResponse.OnNext(res1);
    
    Response<dynamic> res2 = new Response<dynamic>();
    res2.Id = 2;
    res2.Result = new UserContact();
    
    client.WsResponse.OnNext(res2);
    
    Response<dynamic> res3 = new Response<dynamic>();
    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<dynamic, dynamic> 无法转换为 LiveResultPromise<User, User>

    我怎么能做类似的事?

    谢谢您。

    1 回复  |  直到 6 年前
        1
  •  0
  •   Mattia    6 年前

    我已经用这个解决方案解决了我的问题

    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);
    

    如果你知道更好的解决方案,请告诉我。

    谢谢您。