.net子類傳參至泛型基類處理

using System;
using System.Linq.Expressions;
using System.Reflection;
using System.Threading.Tasks;

namespace Gen.ConsoleApp24
{
    class Program
    {
        static async Task Main(string[] args)
        {
            var aliRequestMessage = new AliRequestMessage { ProductInfo = new AliProductInfo { MyVar = new AliVar(), Sale = new AliSale() } };


            //使用泛型做爲傳參類型
            var fun = new Func<RequestMessage<ProductInfo>, Task<string>>(async message =>
            {
                //var productInfo = (ProductInfo<Var, Sale>)message.ProductInfo;//運行時轉換會報錯,如果取值請通過反射或委託回調轉成具體的類型去處理
                Console.WriteLine(message.Name);
                Console.WriteLine(message.GetType().Name);
                Console.WriteLine(message.ProductInfo.GetType().Name);
                return await Task.FromResult(message.Name);
            });
            //await fun(aliRequestMessage);//編譯報錯

            //解決方法1: 定義一個空子類ChildRequestMessage 繼承泛型
            await fun(new JdRequestMessage() { ProductInfo = new JdProductInfo { MyVar = new JdVar(), Sale = new JdSale() } });

            //解決方法2(推薦): 將泛型繼承一個基類,用基類做爲傳參類型
            var fun2 = new Func<RequestMessage, Task<string>>(async message =>
            {
                //var productInfo = (ProductInfo<Var, Sale>)message.ProductInfo;//編譯報錯,如果取值請通過反射或委託回調轉成具體的類型去處理
                Console.WriteLine(message.Name);
                Console.WriteLine(message.GetType().Name);
                //Console.WriteLine(message.ProductInfo.GetType().Name);//編譯報錯
                return await Task.FromResult(nameof(message));
            });
            await fun2(aliRequestMessage);

            //解決方法3: 使用表達式做爲傳參類型
            var funExpr = new Func<Expression<Func<RequestMessage<ProductInfo>, object>>, Task<string>>(async expression =>
           {
               RequestMessage message = null;
               if (expression.NodeType == ExpressionType.Constant)
               {
                   message = (RequestMessage)((ConstantExpression)expression.Body).Value;
               }
               else
               {
                   var memberExpression = (MemberExpression)expression.Body;

                   var @object = ((ConstantExpression)(memberExpression.Expression)).Value;

                   if (memberExpression.Member.MemberType == MemberTypes.Field)
                   {
                       message = (RequestMessage)((FieldInfo)memberExpression.Member).GetValue(@object);
                   }
                   else if (memberExpression.Member.MemberType == MemberTypes.Property)
                   {
                       message = (RequestMessage)((PropertyInfo)memberExpression.Member).GetValue(@object);
                   }
               }
               //var productInfo = (ProductInfo<Var, Sale>)message.ProductInfo;//編譯報錯
               Console.WriteLine(message.Name);
               Console.WriteLine(message.GetType().Name);
               //Console.WriteLine(message.ProductInfo.GetType().Name);//編譯報錯
               return await Task.FromResult(nameof(message));
           });

            await funExpr(p => aliRequestMessage);

            Console.WriteLine("Hello World!");
        }
    }

    public class AliRequestMessage : RequestMessage<AliProductInfo>
    {
        public string AliName { get; set; } = "Ali";
    }
    public class AliProductInfo : ProductInfo<AliVar, AliSale>
    {

    }

    public class AliVar : Var
    {

    }

    public class AliSale : Sale
    {

    }

    public class JdRequestMessage : ChildRequestMessage
    {
        public string JdName { get; set; } = "JD";
    }

    public class JdProductInfo : ProductInfo<JdVar, JdSale>
    {

    }

    public class JdVar : Var
    {

    }

    public class JdSale : Sale
    {

    }

    public class RequestMessage
    {
        public string Name { get; set; } = "xxx";
    }

    public class ChildRequestMessage : RequestMessage<ProductInfo>
    {

    }

    public class RequestMessage<TProductInfo> : RequestMessage where TProductInfo : ProductInfo
    {
        public TProductInfo ProductInfo { get; set; }
    }

    public class ProductInfo
    {

    }
    public class ProductInfo<TVar, TSale> : ProductInfo where TVar : Var where TSale : Sale
    {
        public TVar MyVar { get; set; }

        public TSale Sale { get; set; }
    }

    public class Var
    {
        public string Name { get; set; } = "變體";
    }

    public class Sale
    {
        public string Name { get; set; } = "賣家";
    }
}

運行效果:

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章