Skip to content
This repository has been archived by the owner on Nov 8, 2022. It is now read-only.

Commit

Permalink
proxy: Property get/set via CLR properties
Browse files Browse the repository at this point in the history
  • Loading branch information
arfbtwn committed Oct 14, 2017
1 parent b288288 commit d752fa5
Show file tree
Hide file tree
Showing 7 changed files with 339 additions and 10 deletions.
23 changes: 23 additions & 0 deletions src/BusObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,29 @@ public MessageReader SendMethodCall (string iface, string member, string inSigSt
return retVal;
}

public object SendPropertyGet (string iface, string property)
{
Exception exception;
MessageWriter writer = new MessageWriter ();
writer.Write (iface);
writer.Write (property);

MessageReader reader = SendMethodCall ("org.freedesktop.DBus.Properties", "Get", "ss", writer, typeof(object), out exception);

return reader.ReadValue ();
}

public void SendPropertySet (string iface, string property, object value)
{
Exception exception;
MessageWriter writer = new MessageWriter ();
writer.Write (iface);
writer.Write (property);
writer.Write (typeof(object), value);

SendMethodCall ("org.freedesktop.DBus.Properties", "Set", "ssv", writer, typeof(void), out exception);
}

public void Invoke (MethodBase methodBase, string methodName, object[] inArgs, out object[] outArgs, out object retVal, out Exception exception)
{
Invoke (methodBase, methodName, inArgs, null, out outArgs, out retVal, out exception);
Expand Down
119 changes: 119 additions & 0 deletions src/ExportObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,43 @@ internal static MethodCaller GetMCaller (MethodInfo mi)
return mCaller;
}

internal static MethodCaller GetPropertyCaller(PropertyInfo pi)
{
MethodInfo mi = pi.GetMethod;
MethodCaller mCaller;
if (!mCallers.TryGetValue(mi, out mCaller))
{
mCaller = TypeImplementer.GenGetCall (pi);
mCallers[mi] = mCaller;
}
return mCaller;
}

internal static MethodCaller SetPropertyCaller(PropertyInfo pi)
{
MethodInfo mi = pi.SetMethod;
MethodCaller mCaller;
if (!mCallers.TryGetValue(mi, out mCaller))
{
mCaller = TypeImplementer.GenSetCall (pi);
mCallers[mi] = mCaller;
}
return mCaller;
}

public static ExportObject CreateExportObject (Connection conn, ObjectPath object_path, object obj)
{
return new ExportObject (conn, object_path, obj);
}

public virtual void HandleMethodCall (MessageContainer method_call)
{
if (method_call.Interface == "org.freedesktop.DBus.Properties")
{
HandlePropertyCall (method_call);
return;
}

MethodInfo mi;
if (!methodInfoCache.TryGetValue (method_call.Member, out mi))
methodInfoCache[method_call.Member] = mi = Mapper.GetMethod (Object.GetType (), method_call);
Expand Down Expand Up @@ -148,6 +178,95 @@ public virtual void HandleMethodCall (MessageContainer method_call)
}
}

private void HandlePropertyCall(MessageContainer method_call)
{
Message msg = method_call.Message;
MessageReader msgReader = new MessageReader (msg);
MessageWriter retWriter = new MessageWriter ();

object[] args = MessageHelper.GetDynamicValues (msg);

string face = (string)args[0];

if ("GetAll" == method_call.Member) {
conn.MaybeSendUnknownMethodError (method_call);
return;
}

string name = (string)args[1];

PropertyInfo pi = Object.GetType ().GetProperty (name);

if (null == pi)
{
conn.MaybeSendUnknownMethodError (method_call);
return;
}

MethodCaller pc = null;
MethodInfo mi = null;
Signature outSig, inSig = method_call.Signature;

switch (method_call.Member) {
case "Set":
mi = pi.SetMethod;
pc = SetPropertyCaller (pi);
outSig = Signature.Empty;
break;
case "Get":
mi = pi.GetMethod;
pc = GetPropertyCaller (pi);
outSig = Signature.GetSig (mi.ReturnType);
break;
default:
conn.MaybeSendUnknownMethodError (method_call);
return;
}

Exception raisedException = null;
try {
pc (Object, msgReader, msg, retWriter, null);
} catch (Exception e) {
raisedException = e;
}

Message replyMsg;

if (raisedException == null)
{
MessageContainer method_return = new MessageContainer
{
Type = MessageType.MethodReturn,
ReplySerial = msg.Header.Serial
};
replyMsg = method_return.Message;
replyMsg.AttachBodyTo (retWriter);
replyMsg.Signature = outSig;
}
else {
// BusException allows precisely formatted Error messages.
BusException busException = raisedException as BusException;
if (busException != null)
replyMsg = method_call.CreateError (busException.ErrorName, busException.ErrorMessage);
else if (raisedException is ArgumentException && raisedException.TargetSite.Name == mi.Name)
{
// Name match trick above is a hack since we don't have the resolved MethodInfo.
ArgumentException argException = (ArgumentException)raisedException;
using (System.IO.StringReader sr = new System.IO.StringReader (argException.Message))
{
replyMsg = method_call.CreateError ("org.freedesktop.DBus.Error.InvalidArgs", sr.ReadLine());
}
}
else
replyMsg = method_call.CreateError (Mapper.GetInterfaceName(raisedException.GetType()), raisedException.Message);
}

if (method_call.Sender != null)
replyMsg.Header[FieldCode.Destination] = method_call.Sender;

conn.Send (replyMsg);
}

public object Object {
get;
private set;
Expand Down
1 change: 1 addition & 0 deletions src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ CSFILES = Address.cs \
Introspection.cs \
Mapper.cs \
TypeImplementer.cs \
ReflectionExtensions.cs \
ArgDirection.cs \
ObjectPath.cs \
OSHelpers.cs \
Expand Down
5 changes: 5 additions & 0 deletions src/Protocol/MessageReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,11 @@ public object ReadValue (Type type)
}
}

public object ReadValue()
{
return ReadValue (message.Signature);
}

public object ReadValue (DType dtype)
{
switch (dtype)
Expand Down
41 changes: 41 additions & 0 deletions src/ReflectionExtensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using System.Reflection;
using System.Reflection.Emit;

static class ReflectionExtensions
{
public static bool IsProperty(this MethodBase method)
{
var properties = method.DeclaringType.GetProperties();
foreach (var prop in properties)
{
if (method == prop.GetMethod) return true;
if (method == prop.SetMethod) return true;
}
return false;
}

public static MethodBuilder DefineMethodOverride(this TypeBuilder typeB, MethodInfo declMethod)
{
ParameterInfo[] parms = declMethod.GetParameters();

Type[] parmTypes = new Type[parms.Length];
for (int i = 0; i<parms.Length ; i++)
parmTypes[i] = parms[i].ParameterType;

MethodAttributes attrs = declMethod.Attributes ^ MethodAttributes.Abstract;
attrs ^= MethodAttributes.NewSlot;
attrs |= MethodAttributes.Final;
MethodBuilder method_builder = typeB.DefineMethod(declMethod.Name,
attrs,
declMethod.ReturnType,
parmTypes);

for (int i = 0; i<parms.Length ; i++)
method_builder.DefineParameter (i + 1, parms[i].Attributes, parms[i].Name);

typeB.DefineMethodOverride(method_builder, declMethod);

return method_builder;
}
}
Loading

0 comments on commit d752fa5

Please sign in to comment.