英文:
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 => 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?
答案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<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();
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论