Упрощение:
У нас есть собственный сопоставитель БД от 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 в это ^?