C# create object instance with expression.new

金利 张 25 Reputation points
2024-10-05T07:22:53.52+00:00

I want to using expression to create object instance, at last i got an error. code bellow ` [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)] public class FieldAttribute : Attribute { private bool _isSizeExtracted; private string _size;

    public FieldAttribute(string dataType = null)
    {
        if (!string.IsNullOrWhiteSpace(dataType))
        {
            DataType = dataType.ToLower();
        }
    }

    public int? Index { get; set; }


    public string FieldName { get; set; }

    public bool HasDefaultValue { get; set; }


    public string DataType { get; set; }


    internal string Size
    {
        get
        {
            if (string.IsNullOrWhiteSpace(DataType)) return null;

            if (!_isSizeExtracted)
            {
                _isSizeExtracted = true;

                var i = DataType.IndexOf('(');
                if (i > 0)
                {
                    var j = DataType.IndexOf(')', i);
                    if (j > 0)
                    {
                        //_size = DataType[(i + 1)..j];
                    }
                }
            }

            return _size;
        }
    }
}

internal class TableInfo
{

}

internal class FieldInfoBase
{

    internal int Index { get; set; }


    internal string FieldName { get; set; }


    internal bool HasDefaultValue { get; set; }


    internal string FieldDataType { get; set; }

    internal Type PropertyType { get; set; }


    internal string Size { get; set; }


    internal bool FieldNameSameAsPropertyName { get; set; }

    internal virtual object GetValue(object objInstance) { return null; }
}

internal class FieldInfo<TUserData, TValue> : FieldInfoBase where TUserData : class
{
    private ConcurrentDictionary<Type, long[]> _hashes = null;

    protected bool _isValueType;

    protected Type _realPropertyType;

    public FieldInfo(TableInfo tableInfo, PropertyInfo propertyInfo, FieldAttribute attr, ref int columnIndex)
    {
        _hashes = new ConcurrentDictionary<Type, long[]>();

        HasDefaultValue = attr.HasDefaultValue;
        Size = attr.Size;
        FieldDataType = attr.DataType; 
        Index = attr.Index ?? columnIndex++;

        PropertyName = propertyInfo.Name;
        PropertyType = propertyInfo.PropertyType;

        FieldName = string.IsNullOrWhiteSpace(attr.FieldName) ? PropertyName : attr.FieldName;

        FieldNameSameAsPropertyName = PropertyName.Equals(attr.FieldName);


        if (!IsNullable && !_isValueType)
        {
            IsNullable = true;
        }
    }

    internal string PropertyName { get; private set; }

    internal bool IsPrimaryKey { get; set; }

    internal bool IsNullable { get; set; }

    public void SetValue(TUserData ins, TValue value)
    {

    }
}

public class UserInfo
{
    [Field]
    public int Id { get; set; }

    public int ParentId { get; set; }

    public string Address { get; set; }
}


public static void TestExpressionCreate<TUserData, TValue>() where TUserData : class
{
    var t = typeof(FieldInfo<,>);
    var d = t.MakeGenericType(typeof(TUserData), typeof(TValue));

    var ctor = d.GetConstructor([typeof(TableInfo), typeof(PropertyInfo), typeof(FieldAttribute), typeof(int).MakeByRefType()]);

    var tiExp = Expression.Parameter(typeof(TableInfo));
    var piExp = Expression.Parameter(typeof(PropertyInfo));
    var attrExp = Expression.Parameter(typeof(FieldAttribute));
    var indexExp = Expression.Parameter(typeof(int).MakeByRefType());

    var body = Expression.New(ctor, [tiExp, piExp, attrExp, indexExp]);
    var lambda = Expression.Lambda<Func<FieldInfo<TUserData, TValue>>>(body, [tiExp, piExp, attrExp, indexExp]).CompileFast();


    var table = new TableInfo();
    var pi = typeof(UserInfo).GetProperty("Id");
    var fieldAttr = pi.GetCustomAttribute<FieldAttribute>();
    var columnIndex = 0;

    Stopwatch watch = Stopwatch.StartNew();

    for (int i = 0; i < max; i++)
    {
        var ins = lambda.DynamicInvoke([table, pi, fieldAttr, columnIndex]); <--- error here
    }

    watch.Stop();
    Console.WriteLine(watch.ElapsedTicks);
}


static void Main(string[] args)
{


    TestExpressionCreate<UserInfo, int>();
    TestActivatorCreate();

    Console.ReadLine();
}
Developer technologies | C#
Developer technologies | C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
0 comments No comments
{count} vote

1 answer

Sort by: Most helpful
  1. Joao Ricardo Rodrigues De La Cruz Baptista 90 Reputation points
    2025-10-13T05:17:12.36+00:00

    Hi @金利 张,

    I create locally some project just to try reproduce of the same issue, and I think this could be a way to go...

    
    [AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
    public class FieldAttribute : Attribute
    {
        private bool _isSizeExtracted; private string _size;
    
        public FieldAttribute(string dataType = null) { if (!string.IsNullOrWhiteSpace(dataType)) { DataType = dataType.ToLower(); } }
    
        public int? Index { get; set; }
    
        public string FieldName { get; set; }
    
        public bool HasDefaultValue { get; set; }
    
        public string DataType { get; set; }
    
        internal string Size { get { if (string.IsNullOrWhiteSpace(DataType)) return null; if (!_isSizeExtracted) { _isSizeExtracted = true; var i = DataType.IndexOf('('); if (i > 0) { var j = DataType.IndexOf(')', i); if (j > 0) { _size = DataType[(i + 1)..j]; } } } return _size; } }
    }
    
    internal class TableInfo
    {
        internal string TableName { get; set; }
    }
    
    internal class FieldInfoBase
    {
    
        internal int Index { get; set; }
    
        internal string? FieldName { get; set; }
    
        internal bool HasDefaultValue { get; set; }
    
        internal string? FieldDataType { get; set; }
    
        internal Type? PropertyType { get; set; }
    
        internal string? Size { get; set; }
    
        internal bool FieldNameSameAsPropertyName { get; set; }
    
        internal virtual object? GetValue(object objInstance) { return null; }
    }
    
    internal class FieldInfo<TUserData, TValue> : FieldInfoBase where TUserData : class
    {
        private ConcurrentDictionary<Type, long[]>? _hashes = null;
    
        protected bool _isValueType;
    
        protected Type? _realPropertyType;
    
        public FieldInfo(TableInfo tableInfo, PropertyInfo propertyInfo, FieldAttribute attr, ref int columnIndex)
        {
            _hashes = new ConcurrentDictionary<Type, long[]>();
    
            HasDefaultValue = attr.HasDefaultValue;
            Size = attr.Size;
            FieldDataType = attr.DataType;
            Index = attr.Index ?? columnIndex++;
    
            PropertyName = propertyInfo.Name;
            PropertyType = propertyInfo.PropertyType;
            _realPropertyType = propertyInfo.PropertyType;
    
            FieldName = string.IsNullOrWhiteSpace(attr.FieldName) ? PropertyName : attr.FieldName;
    
            FieldNameSameAsPropertyName = PropertyName.Equals(attr.FieldName);
    
            if (!IsNullable && !_isValueType)
            {
                IsNullable = true;
            }
        }
    
        internal string PropertyName { get; private set; }
    
        internal bool IsPrimaryKey { get; set; }
    
        internal bool IsNullable { get; set; }
    
        public static void SetValue(TUserData ins, TValue value)
        {
            
        }
    }
    
    public class UserInfo
    {
        [Field]
        public int Id { get; set; }
    
        public int ParentId { get; set; }
    
        public string? Address { get; set; }
    }
    

    Thank you.

    @Johnnie

    I hope this helps you.

    If this response resolves your issue, please accept the answer and, if helpful, click the “Upvote” button. Your feedback helps us improve and assist others more effectively.

    0 comments No comments

Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.