繁体   English   中英

Dapper如何设置只读属性?

[英]How can Dapper set a read-only property?

我注意到以下与 Dapper 和 C# 只读自动属性(在 C# 6 中介绍)相关的行为。

Dapper 能够 map 一个带有只读属性集的 class 的实例,根据我对只读属性如何工作的理解,这应该是不可能的。

以下代码演示了这一点:

using Dapper;
using Npgsql;
using System;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Model
    {
        public long Id { get; }
    }

    class Program
    {
        static async Task<Model> GetData()
        {
            using (var connection = new NpgsqlConnection("..."))
            {
                await connection.OpenAsync();

                var sql = @"
                    SELECT 22 AS Id";

                return await connection.QuerySingleAsync<Model>(sql);
            }
        }

        static async Task Main(string[] args)
        {
            var model = await GetData();
            Console.WriteLine(model.Id);

            var model2 = new Model();
            //model2.Id = 22;

            var model3 = new Model
            {
                //Id = 22;
            };
        }
    }
}

注释掉的行会按预期产生编译时错误CS0200

不需要数据库设置,只需一个有效的 SQL 连接(我使用的是 Postgres)。 从 GetData 返回的 model 设置了 Id 属性,如果我尝试手动创建 Model class 的实例,我无法设置它的 Id 属性,因为它是只读的。

我想知道 Dapper 如何设置该属性? 我尝试遵循 Dapper 存储库中的代码,但它超出了我的理解水平。

我设法跟进了SqlMapper.cs#L1530 ,这是我认为魔法正在发生的地方,但超出这一点就很难跟进了。

如果有人能简单地解释一下,我将不胜感激:)

谢谢你。

在幕后,您的声明:

public long Id { get; }

实际上编译成如下C#代码:

[CompilerGenerated]
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private readonly long <Id>k__BackingField;

public long Id
{
    [CompilerGenerated]
    get
    {
        return <Id>k__BackingField;
    }
}

使用反射,你可以做一些非常疯狂的事情。 其中之一就是设置标记为readonly的字段的值。 (这有一些有趣的含义,比如能够将string.Empty设置为任何你想要的!)

在 Dapper 的例子中,它有效地做了以下事情,但有更多的错误检查:

Model m = <instance of your Model class>;
Type t = m.GetType();
string propertyName = "Id"; // read using Reflection
FieldInfo fi = t.GetField("<" + propertyName + ">k__BackingField",
    BindingFlags.Instance | BindingFlags.NonPublic);
if (fi != null)
    fi.SetValue(m, 22); // 22 = value read from DB

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM