使用FastMember将值赋给Nullable <t>

时间:2016-10-28 13:53:15

标签: c# properties nullable fastmember

我已使用此函数

为Properties和嵌套属性成功分配了值
CREATE TRIGGER T_TableTokay_I
on dbo.test_tokay
after insert    
as
set nocount on

insert into dbo.edit(inserted.HAZ_ID/* Columns in table b */)
select a.HAZ_ID /* Columns from table a */
from
    test_tokay a

但是,赋值会抛出InvalidCastException。如何使用FastMember指定可空值?例如

DECLARE @list_item TABLE ( unit NVARCHAR(5),bank NVARCHAR(5),curr INT)
INSERT INTO @list_item VALUES ('PCB','SBI',1000),('PCB','SBI',1000),
('PCB','SBI',1000),('PTB','SBI',1000),('PTB','SBI',1000),
('PTB','SBI',1000)

SELECT bank,
SUM(CASE WHEN unit='PCB' THEN curr END) PCBUnitSum,
SUM(CASE WHEN unit='PTB' THEN curr END) PTBUnitSum
FROM ( SELECT unit,bank,SUM(curr)curr FROM @list_item 
group by unit,bank ) A GROUP BY bank

2 个答案:

答案 0 :(得分:5)

FastMember与其工具箱中的类型转换没有任何关系,因此这是我提出的解决方案,作为FastMember ObjectAccessor的扩展方法:

public static class FastMemberExtensions
{
    public static void AssignValueToProperty(this ObjectAccessor accessor, string propertyName, object value)
    {
        var index = propertyName.IndexOf('.');

        if (index == -1)
        {
            var targetType = Expression.Parameter(accessor.Target.GetType());
            var property = Expression.Property(targetType, propertyName);

            var type = property.Type;
            type = Nullable.GetUnderlyingType(type) ?? type;
            value = value == null ? GetDefault(type) : Convert.ChangeType(value, type);
            accessor[propertyName] = value;
        }
        else
        {
            accessor = ObjectAccessor.Create(accessor[propertyName.Substring(0, index)]);
            AssignValueToProperty(accessor, propertyName.Substring(index + 1), value);
        }
    }

    private static object GetDefault(Type type)
    {
        return type.IsValueType ? Activator.CreateInstance(type) : null;
    }
}

可以这样调用:

var accessor = ObjectAccessor.Create(t); // t is instance of SomeType
accessor.AssignValueToProperty("Nested.Property", value); // t.Nested.Property = value

答案 1 :(得分:3)

FastMember不会为您转换类型。 100是一个int literal,但target属性是decimal?类型。没有从int到decimal的隐式转换? (或十进制)。 100.0是Double literal,它隐式转换为decimal?,因此赋值将成功。

public class A
{
    public double? SomeValue { get; set; }
}

public static class Sample
{
    public static void Go()
    {
        var a = new A();
        var accessor = ObjectAccessor.Create(a);
        accessor["SomeValue"] = 100.0; // succeeds
        accessor["SomeValue"] = 100M; // succeeds
        accessor["SomeValue"] = null; // succeeds
        accessor["SomeValue"] = 100; // throws, can't convert from int to decimal?
    }
}

如果没有隐式转换,您必须在代码中执行必要的转换。

隐含转化:

https://msdn.microsoft.com/en-us/library/y5b434w4.aspx

明确转换:

https://msdn.microsoft.com/en-us/library/yht2cx7b.aspx