Этот вопрос почти исключительно для учебных целей.В качестве среды используется движок Unity 3D.
Я использовал классы RealProxy и MarhalByRefObject в C # для украшения одного из моих классов.В частности, я создал универсальный прокси-класс, используя конструктор ниже.Класс, который я декорирую, также имеет атрибут SerializableAttribute, наряду с наследованием от MarshalByRefObject.
public DynamicProxy(T decorated) : base(typeof(T))
{
}
Чтобы получить декорированный объект, простейший код (без декорации) выглядит следующим образом
ClassA toDecorate = new ClassA();
DynamicProxy proxy = new DynamicProxy<ClassA>(toDecorate);
Debug.Log(proxy.GetTransparentProxy() as ClassA);
Debug.Log((ClassA)proxy.GetTransparentProxy());
Вот где это стало странным.Я проверил тип по отражению, и он действительно был того же типа, что и объект, который я хотел украсить.Однако запутанная часть заключается в том, что при обычном приведении (ClassA) я получаю ссылку на декорированный объект, тогда как при использовании оператора as возвращается нулевая ссылка.
Я обнаружил такое поведение, когдаЯ тестировал свою сборку для Unity v. 2019.1.8f1.Версия среды выполнения сценариев и используемый мной API эквивалентны .NET 4.x.
Если у кого-то были подобные проблемы, я хотел бы услышать о них, так как приведение и поведение оператора по-разному не должно происходить и может привести к огромной потере времени и усилий.Я на самом деле не спрашиваю решения, а скорее мнения людей, которые могут иметь лучшее представление, чем я, или столкнулись с аналогичной проблемой.
ПРИМЕЧАНИЕ : Такое поведение не происходитесли я просто сделаю
ClassA t = new ClassA();
object o = t;
Debug.Log(o as ClassA);
Debug.Log((ClassA)o);
РЕДАКТИРОВАТЬ : При дополнительном расследовании мое внимание привлекло то, что оператор as по сути делает это
E is T ? (T)(E) : (T)null
и что происходитчто оператор is возвращает false.
Предоставляя здесь код со всем, что необходимо для воспроизведения проблемы.
public class HelloThere: MarshalByRefObject
{
public void DoStuff()
{
//Do some stuff here
Debug.Log("Doing some stuff");
}
}
public class Proxy<T> : System.Runtime.Remoting.Proxies.RealProxy
{
private T _decorated;
public Proxy(T decorated): base(typeof(T))
{
_decorated = decorated;
}
public override IMessage Invoke(IMessage msg)
{
//Do Stuff Before Function
//Call Function
var methodCall = msg as IMethodCallMessage;
var methodInfo = methodCall.MethodBase as System.Reflection.MethodInfo;
try
{
var result = methodInfo.Invoke(_decorated, methodCall.InArgs);
return new ReturnMessage(
result, null, 0, methodCall.LogicalCallContext, methodCall);
//Do Stuff After function
}
catch (Exception e)
{
return new ReturnMessage(e, methodCall);
}
}
}
Кроме того, код для проверки того, что возвращает каждый «кастинг»:
Proxy<HelloThere> proxy = new Proxy<HelloThere>(new HelloThere());
Debug.Log(proxy.GetTransparentProxy() as HelloThere);
Debug.Log((HelloThere)proxy.GetTransparentProxy());