你可以将`.ConvertToProvider`从`Func<object, object>`转换为更精确的类型吗?

huangapple go评论64阅读模式
英文:

Can I convert a .ConvertToProvider from Func<object, object> to a more precise type?

问题

My table T_SHIP has a column FULL_TANK, containing "Y" if the ship's fuel tank is full, "N" if it isn't, and Null if the ship doesn't have a tank, such as a sailing ship.

I define an entity property for that column as such:

p_etbTable.Property(t => t.HasFullTank).HasColumnName("FULL_TANK")
                                       .HasColumnType("varchar(1)")
                                       .HasConversion(ConversionsHelper.BooleanToY_N);

with BooleanToY_N a simple ValueConverter object:

public static ValueConverter<bool?, string> BooleanToY_N =
        new ValueConverter<bool?, string>(b => b.HasValue ? (b.Value ? "Y" : "N") : null,
                                          s => s == "Y");

In my code, I want to be able to access the values "Y" and "N" directly from BooleanToY_N, as an alternative to constants.

IConventionAnnotation z_annConverterHasFullTank = 
            ((IConventionAnnotatable)new MyDbContext().Model
                                        .GetEntityTypes()
                                        .FirstOrDefault(et => et.ClrType == typeof(TShip))
                                        .GetProperties()
                                        .First(pr => pr.Name == nameof(TShip.HasFullTank)))
                                        .GetAnnotation(nameof(EF_Storage.ValueConversion.ValueConverter));
EF_Storage.ValueConversion.ValueConverter<bool?, string> z_vcoConverterHasFullTank =
            (EF_Storage.ValueConversion.ValueConverter<bool?, string>)z_annConverterHasFullTank.Value;

Func<object, object> z_funConversionHasFullTank = z_vcoConverterHasFullTank.ConvertToProvider;

and then use z_funConversionHasFullTank.Invoke() by passing it false or true to get "N" or "Y", respectively, then use .ToString() to convert it to a string.

This works quite well, but to simplify the use of z_funConversionHasFullTank, I'd like to define it as Func<bool?, string>.

When I do, the compiler informs me that it cannot convert Func<object, object> to Func<bool?, string>. Still, since there's a Func<bool?, string> in there I feel I should be able to get it out. Does anyone have an idea how that could be done?

英文:

My table T_SHIP has a column FULL_TANK, containing "Y" if the ship's fuel tank is full, "N" if it isn't, and Null if the ship doesn't have a tank, such as a sailing ship.

I define an entity property for that column as such:

p_etbTable.Property(t =&gt; t.HasFullTank).HasColumnName(&quot;FULL_TANK&quot;)
                                       .HasColumnType(&quot;varchar(1)&quot;)
                                       .HasConversion(ConversionsHelper.BooleanToY_N);

with BooleanToY_N a simple ValueConverter object:

public static ValueConverter&lt;bool?, string&gt; BooleanToY_N =
        new ValueConverter&lt;bool?, string&gt;(b =&gt; b.HasValue ? (b.Value ? &quot;Y&quot; : &quot;N&quot;) : null,
                                          s =&gt; s == &quot;Y&quot;);

In my code, I want to be able to access the values "Y" and "N" directly from BooleanToY_N, as an alternative to constants.

IConventionAnnotation z_annConverterHasFullTank = 
            ((IConventionAnnotatable)new MyDbContext().Model
                                        .GetEntityTypes()
                                        .FirstOrDefault(et =&gt; et.ClrType == typeof(TShip))
                                        .GetProperties()
                                        .First(pr =&gt; pr.Name == nameof(TShip.HasFullTank)))
                                        .GetAnnotation(nameof(EF_Storage.ValueConversion.ValueConverter));
EF_Storage.ValueConversion.ValueConverter&lt;bool?, string&gt; z_vcoConverterHasFullTank =
            (EF_Storage.ValueConversion.ValueConverter&lt;bool?, string&gt;)z_annConverterHasFullTank.Value;

Func &lt;object, object&gt; z_funConversionHasFullTank = z_vcoConverterHasFullTank.ConvertToProvider.;

and then use z_funConversionHasFullTank.Invoke() by passing it false or true to get "N" or "Y", respectively, then use .ToString() to convert it to a string.

This works quite well, but to simplify the use of z_funConversionHasFullTank, I'd like to define it as Func&lt;bool?, string&gt;.

When I do, the compiler informs me that it cannot convert Func&lt;object, object&gt; to Func&lt;bool?, string&gt;. Still, since there's a Func&lt;bool?, string&gt; in there I feel I should be able to get it out. Does anyone have an idea how that could be done?

答案1

得分: 1

Your expression is of the wrong type, must be:

ValueConverter<bool?, string?>

Because the string can also be null. Then it has a bug, it won't return null when the provider (string) is null but false instead:

new ValueConverter<bool?, string?>(
    b => b.HasValue ? (b.Value ? "Y" : "N") : null, 
    s => s == null ? null : s == "Y"
);

(Or s => s == null ? null : (bool?)s == "Y" for earlier C# versions).

Finally, you're right in that ConvertToProvider is a Func<object?, object?> and that you can't cast that to Func<bool?, string?>, but luckily there's also a ConvertToProviderExpression which is an Expression<Func<bool?, string?>>:

Func<bool?, string?> toProvider = z_vcoConverterHasFullTank.ConvertToProviderExpression.Compile();
英文:

Your expression is of the wrong type, must be:

ValueConverter&lt;bool?, string?&gt;

Because the string can also be null. Then it has a bug, it won't return null when the provider (string) is null but false instead:

new ValueConverter&lt;bool?, string?&gt;(
    b =&gt; b.HasValue ? (b.Value ? &quot;Y&quot; : &quot;N&quot;) : null, 
    s =&gt; s == null ? null : s == &quot;Y&quot;
);

(Or s =&gt; s == null ? null : (bool?)s == &quot;Y&quot; for earlier C# versions).

Finally, you're right in that ConvertToProvider is a Func&lt;object?, object?&gt; and that you can't cast that to Func&lt;bool?, string?&gt;, but luckily there's also a ConvertToProviderExpression which is an Expression&lt;Func&lt;bool?, string?&gt;&gt;:

Func&lt;bool?, string?&gt; toProvider = z_vcoConverterHasFullTank.
    ConvertToProviderExpression.Compile();

huangapple
  • 本文由 发表于 2023年3月9日 20:03:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/75684358.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定