为了账号安全,请及时绑定邮箱和手机立即绑定

编译时设计基于模型的系统

编译时设计基于模型的系统

C#
江户川乱折腾 2021-11-07 19:38:07
我有一个模型类很少的系统,每个类都有另一个成员,但所有模型的行为都是相同的-例如,所有模型都是来自用户的请求输入格式为: Hi, Please enter {MemberName} value as {MemberType}:并将输入转换为 MemberType。因为这打算成为库,所以我希望在每个模型中我都可以在编译时访问他的成员(或类似成员)myModel.get("memberName"),而不是 by ,而是 bymyModel.memberName或myModel.get(modelEnum.MemberName)ormyModel.ListOfMember[0]或者也许Factory.getMember(myModel, SpecificModelMembersList[0])等等。我不需要在运行时添加或删除成员,只需创建一个在编译时添加它们的好方法,而不是更改将成员添加到模型类的所有代码。你会如何设计它?我使用 C#。谢谢你,你可以建议一个英文修复。
查看完整描述

1 回答

?
MYYA

TA贡献1868条经验 获得超4个赞

我的想法是使用 lambda 表达式以简单直观的方式访问属性信息数据(使用 IntelliSense 支持和所有可用的重构)。演示该方法的代码如下。


using System;

using System.Linq.Expressions;

using System.Reflection;


namespace ConsoleAppTest2

{

    class Program

    {

        static void Main(string[] args)

        {

            var myModel = new MyModel();


            var cmb = ConsoleModelBuilder<MyModel>.RequestFromComsole(myModel)

                .FillProp(x=>x.MethodName)

                .FillProp(x => x.Birthday);

            Console.ReadLine();

        }

    }


    internal class MyModel

    {

        public int MethodName { get; set; }

        public DateTime Birthday { get; set; }


    }


    internal class ConsoleModelBuilder<T>

    {

        public T Model { get; private set; }


        public static ConsoleModelBuilder<T> RequestFromComsole(T obj)

        {

            return new ConsoleModelBuilder<T>() { Model = obj };



        }


        public ConsoleModelBuilder<T> FillProp<TProperty>(Expression<Func<T, TProperty>> propertyLambda)

        {

            PropertyInfo info = GetPropertyInfo(Model, propertyLambda);


            Console.WriteLine($"Hi, Please enter {info.Name} value as {info.PropertyType.Name}:");

            //Code to parse console input and fill property of Model

            return this;

        }



        public PropertyInfo GetPropertyInfo<TSource, TProperty>(

    TSource source,

    Expression<Func<TSource, TProperty>> propertyLambda)

        {

            Type type = typeof(TSource);


            MemberExpression member = propertyLambda.Body as MemberExpression;

            if (member == null)

                throw new ArgumentException(string.Format(

                    "Expression '{0}' refers to a method, not a property.",

                    propertyLambda.ToString()));


            PropertyInfo propInfo = member.Member as PropertyInfo;

            if (propInfo == null)

                throw new ArgumentException(string.Format(

                    "Expression '{0}' refers to a field, not a property.",

                    propertyLambda.ToString()));


            if (type != propInfo.ReflectedType &&

                !type.IsSubclassOf(propInfo.ReflectedType))

                throw new ArgumentException(string.Format(

                    "Expression '{0}' refers to a property that is not from type {1}.",

                    propertyLambda.ToString(),

                    type));


            return propInfo;

        }

    }

}

访问 PropertyInfo 的核心方法来自 StackOverflow 问题Retrieving Property name from lambda expression。


查看完整回答
反对 回复 2021-11-07
  • 1 回答
  • 0 关注
  • 150 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信