/// <summary>
/// 外部事件应该在OnStartup事件中注册,
/// 否则可能会无法执行
/// </summary>
class ExternalEventManagement
{
bool _register = false;
Dictionary<ExternalEventType, IExternalEventHandlerExt> _dicEventHandler = null;
Dictionary<ExternalEventType, ExternalEvent> _dicExternalEvent = null;
ExternalEventManagement()
{
_dicEventHandler = new Dictionary<ExternalEventType, IExternalEventHandlerExt>();
_dicExternalEvent = new Dictionary<ExternalEventType, ExternalEvent>();
}
public static readonly ExternalEventManagement Instance = new ExternalEventManagement();
/// <summary>
/// 外部事件必须在OnStartup事件中注册
/// </summary>
public void RegisterExternalEvent()
{
if (_register)
throw new Exception("外部事件重复注册!!!");
_register = true;
var ass = System.Reflection.Assembly.GetExecutingAssembly();
var externalEventTypes = ass.GetTypes().Where(o => o.GetInterfaces().Contains(typeof(IExternalEventHandlerExt)) &&
o.GetCustomAttributes(typeof(ExternalEventAttribute), false).Length > 0);
foreach (var item in externalEventTypes)
{
var handle = ass.CreateInstance(item.FullName) as IExternalEventHandlerExt;
var attrs = item.GetCustomAttributes(typeof(ExternalEventAttribute), false);
var exAttr = attrs.FirstOrDefault(o => o is ExternalEventAttribute);
if (exAttr != null)
{
var externalEventType = (exAttr as ExternalEventAttribute).ExternalEventType;
var externalEvent = ExternalEvent.Create(handle);
_dicEventHandler.Add(externalEventType, handle);
_dicExternalEvent.Add(externalEventType, externalEvent);
}
else
{
#if DEBUG
System.Windows.MessageBox.Show(
string.Format("外部事物类型: {0} 未实现自动注册, 未添加ExternalEventAttribute特性.", handle.GetType().FullName),
"警告消息",
System.Windows.MessageBoxButton.OK,
System.Windows.MessageBoxImage.Error);
#endif
}
}
Framework.App.Instance.Loger.Log("外部事件注册完成");
}
public void RaiseExternalEvent(ExternalEventType externalEventType, params object[] paramList)
{
System.Diagnostics.Debug.Assert(_dicExternalEvent.ContainsKey(externalEventType));
_dicEventHandler[externalEventType].SetParams(paramList);
_dicExternalEvent[externalEventType].Raise();
}
}
/// <summary>
/// 外部事务扩展
/// </summary>
public interface IExternalEventHandlerExt : IExternalEventHandler
{
/// <summary>
/// 设置 外部事务参数
/// </summary>
/// <param name="paramList"></param>
void SetParams(params object[] paramList);
}
/// <summary>
/// 外部事件特性,用来自动注册
///
/// 外部事件一定是有空构造函数的类, 否则反射失败
/// </summary>
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public class ExternalEventAttribute : Attribute
{
public ExternalEventType ExternalEventType { get; private set; }
public ExternalEventAttribute(ExternalEventType externalEventType)
{
ExternalEventType = externalEventType;
}
}
public enum ExternalEventType
{
/// <summary>
/// 打开本地文件并激活显示
/// </summary>
eOpenFileDocument = 10,
eExeCommand = 20,
}
[ExternalEvent(ExternalEventType.eExeCommand)]
class ExternalEventHandler : IExternalEventHandlerExt
{
Action<UIApplication> _action = null;
public void Execute(UIApplication app)
{
try
{
_action.Invoke(app);
}
catch (Exception ex)
{
App.Instance.Loger.Error(ex);
MessageBox.Show(ex.Message, "错误消息", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
public string GetName()
{
return "ExternalEventHandler";
}
public void SetParams(params object[] paramList)
{
_action = paramList[0] as Action<UIApplication>;
}
}
外部事件主要使用场景是:在非模态框中对document进行写操作,因为在非revit主线程中开启事务会异常。
方法使用说明:
1、自定义类实现IExternalEventHandlerExt接口,并且关联ExternalEventAttribute特性
2、ExternalEventManagement.Instance.RegisterExternalEvent()注册,它会自动注册所有实现了IExternalEventHandlerExt接口的类
3、使用ExternalEventManagement.Instance.RaiseExternalEvent(xxx,xxx),启动外部事件,指定类型,还可以传递参数。