internal sealed class EventSubscriberModel
{
// Used to dispatch events to the UI's synchronization context.
private static AsyncOperation asyncOperation =
AsyncOperationManager.CreateOperation(null);
// The owner of the model.
private EventBroker owner;
// The client's instance (if any).
private WeakReference client;
// The client's type.
private Type clientType;
// The client's event handler metadata.
private MethodInfo methodInfo;
// Used to dispatch events to the UI's synchronization context.
private SendOrPostCallback synchronizedCallback;
public EventSubscriberModel(
EventBroker owner,
object client,
Type clientType,
MethodInfo methodInfo,
bool synchronize
)
{
// Sanity check the arguments before using them.
Guard.ThrowIfNull(owner, "owner");
Guard.ThrowIfNull(clientType, "clientType");
Guard.ThrowIfNull(methodInfo, "methodInfo");
// Get the handler method's signature.
ParameterInfo[] parms = methodInfo.GetParameters();
// Are the number of parameters incorrect?
if (parms.Length != 2)
throw new TargetParameterCountException();
// Is the first parameter the wrong type?
if (!parms[0].ParameterType.IsAssignableFrom(typeof(object)))
throw new ArgumentException(
string.Format(
CultureInfo.CurrentCulture,
Resources.EventBrokerHandlerModel_TypeAssign,
"object"
));
// Is the second parameter the wrong type?
if (!parms[1].ParameterType.IsAssignableFrom(typeof(EventArgs)))
throw new ArgumentException(
string.Format(
CultureInfo.CurrentCulture,
Resources.EventBrokerHandlerModel_TypeAssign,
"EventArgs"
));
// Save the fields.
this.owner = owner;
this.client = (client != null) ? new WeakReference(client) : null;
this.clientType = clientType;
this.methodInfo = methodInfo;
// Should we create a synchronization delegate?
if (synchronize)
this.synchronizedCallback = new SendOrPostCallback(
SynchronizedCallback
);
}
public void FireMessage(object[] args)
{
// Should we forward the event directly or dispatch it to
// the UI's synchronization context?
if (synchronizedCallback == null)
methodInfo.Invoke(
(client != null) ? client.Target : null,
args
);
else
asyncOperation.Post(
synchronizedCallback,
args
);
}
public override bool Equals(
object obj
)
{
// Sanity check the argument before using it.
Guard.ThrowIfNull(obj, "obj");
// Is the object the wrong type?
if (obj.GetType() != typeof(EventSubscriberModel))
return false;
// Recover a reference to the model.
EventSubscriberModel model = (EventSubscriberModel)obj;
// Compare the instances and return the results.
if (model.client != null && client != null &&
(model.client.Target != client.Target))
return false;
if (model.clientType != clientType)
return false;
if (model.methodInfo != methodInfo)
return false;
return true;
}
public override int GetHashCode()
{
return base.GetHashCode() +
client.GetHashCode() +
clientType.GetHashCode() +
methodInfo.GetHashCode();
}
private void SynchronizedCallback(object state)
{
methodInfo.Invoke(
(client != null) ? client.Target : null,
(object[])state
);
}
}