Приведение к объекту с помощью GetType? - PullRequest
0 голосов
/ 09 июля 2020

Упрощение:

У нас есть собственный сопоставитель БД от SqlDataReader до Entity.

В нормальных условиях это так:

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; }
}

Одно замечание заключается в том, что эта строка:

object s = (int?)1;

Здесь для имитации SqlDataReader, который обертывает значение как Object. В отладке я вижу это как Object{int}

Все в порядке, работает.

Так в чем же проблема?

Проблема в том, что тип в БД smallint, что является Short в C#, а тип в сущности - int?

Итак, в основном происходит следующее:

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

Что приводит к исключению :

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()

Я уже знаю, как это решить:

Это можно сделать, изменив:

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

на

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

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

Вопрос:

Как я могу cast s указать тип свойства объекта?

(int?)(short?)s

Я уже знаю, как получить тип из property:

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

но как я могу преобразовать s в это ^?

...