0

Simplification :

We have our own DB mapper from SqlDataReader to Entity.

In normal circumstances, this is the case :

void Main()
{
    object s = (int?)1;
    MyClass newObjectToReturn = Activator.CreateInstance<MyClass>();
    typeof(MyClass).InvokeMember("MyProperty", BindingFlags.SetProperty, null, newObjectToReturn, new Object[] { s });



}
class MyClass
{
    public int? MyProperty { get; set; }
}

One thing to mention is that this line :

object s = (int?)1;

Is here to simulate the SqlDataReader which wraps the value as Object. In debug, I see it as Object{int}

All Ok and works.

So where is the problem?

The problem is that the type in DB is smallint , which is a Short in C# , and the type in the entity is an int?

So basically what's happening is this :

object s = (short?)1;
int? MyProperty  = (int?)s;

Which yields to exception :

Method 'UserQuery+MyClass.MyProperty' not found.

   at System.RuntimeType.InvokeMember(String name, BindingFlags bindingFlags, Binder binder, Object target, Object[] providedArgs, ParameterModifier[] modifiers, CultureInfo culture, String[] namedParams)
   at System.Type.InvokeMember(String name, BindingFlags invokeAttr, Binder binder, Object target, Object[] args)
   at UserQuery.Main() in C:\Users\royin\AppData\Local\Temp\LINQPad5\_oexzmkdz\query_deibtt.cs:line 33
   at LINQPad.ExecutionModel.ClrQueryRunner.Run()
   at LINQPad.ExecutionModel.Server.RunQuery(QueryRunner runner)
   at LINQPad.ExecutionModel.Server.StartQuery(QueryRunner runner)
   at LINQPad.ExecutionModel.Server.<>c__DisplayClass153_0.<ExecuteClrQuery>b__0()
   at LINQPad.ExecutionModel.Server.SingleThreadExecuter.Work()
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   at System.Threading.ThreadHelper.ThreadStart()

I already know how to solve it :

It's by changing :

typeof(MyClass).InvokeMember("MyProperty", BindingFlags.SetProperty, null, newObjectToReturn, new Object[] { s });

to

typeof(MyClass).InvokeMember("MyProperty", BindingFlags.SetProperty, null, newObjectToReturn, new Object[] { (int?)(short?)s });

// btw , this also works : `(int?)(dynamic)s`

Question:

How can I cast s to the entity's property type ?

(int?)(short?)s

I already know how to get type from the property :

newObjectToReturn.GetType().GetProperties().Where(otr =>otr.Name== "MyProperty").First().PropertyType

but how can I cast s to this ^ ?

timnavigate
  • 741
  • 4
  • 12
  • 23
Royi Namir
  • 144,742
  • 138
  • 468
  • 792
  • `Convert.ChangeType` can help you in some cases (but not completely; its lack of support for nullable types is a problem, for example, necessitating separate checks). – Jeroen Mostert Jul 09 '20 at 11:10
  • Convert.ChangeType , didn't work for me becuase of the nullable... – Royi Namir Jul 09 '20 at 11:13
  • You can use `Nullable.GetUnderlyingType` (combined with `null` checks) to handle them as a special case. – Jeroen Mostert Jul 09 '20 at 11:14
  • what happens if let to use `var`? – timnavigate Jul 09 '20 at 11:16
  • I have a nuget package that might help, it's pre-release because I'm not convinced I have covered all conversion combinations, but you can test it. It's called "converted" and you have to check pre-release in the nuget package manager. It will handle enums and nullable types as well as all the other (well, I hope) conversions you'd expect. – Lasse V. Karlsen Jul 09 '20 at 11:20
  • @RoyiNamir could you explain why do you use `Nullable` at all? – timnavigate Jul 09 '20 at 11:23
  • @timnavigate value from db can be null.... – Royi Namir Jul 09 '20 at 11:35
  • @RoyiNamir maybe this article will help you: https://learn.microsoft.com/en-us/dotnet/api/system.type.invokemember?view=netcore-3.1#System_Type_InvokeMember_System_String_System_Reflection_BindingFlags_System_Reflection_Binder_System_Object_System_Object___ – timnavigate Jul 09 '20 at 11:44
  • @RoyiNamir `db's value is null` is bad design. There is a discussion in this Q&A's post: https://stackoverflow.com/questions/163434/are-nulls-in-a-relational-database-okay – timnavigate Jul 09 '20 at 12:00
  • @timnavigate I don't think so. anyway this is the case and I'm seeking a soution for this situation – Royi Namir Jul 09 '20 at 12:02

0 Answers0