init
This commit is contained in:
1
DataPRO/DataPRO.Core/.svn/entries
Normal file
1
DataPRO/DataPRO.Core/.svn/entries
Normal file
@@ -0,0 +1 @@
|
||||
12
|
||||
1
DataPRO/DataPRO.Core/.svn/format
Normal file
1
DataPRO/DataPRO.Core/.svn/format
Normal file
@@ -0,0 +1 @@
|
||||
12
|
||||
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("DataPro.Core")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("DataPro.Core")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2016")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("bdf5ad7a-51db-4ad0-8186-d1ead7405848")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,216 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using System.ComponentModel.Composition.Hosting;
|
||||
using System.ComponentModel.Composition.ReflectionModel;
|
||||
using System.Linq;
|
||||
using DataPro.Core.Config;
|
||||
|
||||
namespace DataPro.Core.PluginLib
|
||||
{
|
||||
/// <summary>
|
||||
/// PluginManager class to manage MEF plugins
|
||||
/// NOTE: This class has to be thread safe
|
||||
/// </summary>
|
||||
public class PluginManager
|
||||
{
|
||||
// reference to singleton plugin manager
|
||||
private static PluginManager _pluginManager;
|
||||
|
||||
/// <summary>
|
||||
/// MEF catalog
|
||||
/// </summary>
|
||||
private AggregateCatalog PluginCatalog { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// MEF container
|
||||
/// </summary>
|
||||
private CompositionContainer PluginContainer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Thread lock
|
||||
/// </summary>
|
||||
private static readonly object ThreadLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Constructor that intializes catalog and container
|
||||
/// </summary>
|
||||
private PluginManager()
|
||||
{
|
||||
// Create MEF catalog
|
||||
PluginCatalog = new AggregateCatalog();
|
||||
//PluginCatalog = new AggregateCatalog(new AssemblyCatalog(typeof(MediaTypeNames.Application).Assembly));
|
||||
|
||||
// Get plugin folder from App.Config;
|
||||
var pcsh = (PluginConfigSectionHandler)DataProConfig.GetSection("DataPro.Core.PluginLib.Config");
|
||||
if (pcsh == null) throw new Exception("Unable to retrieve plugin config data from DataPro.config (DataPro.Core.PluginLib.Config)");
|
||||
|
||||
|
||||
foreach (FilterHashElement element in pcsh.HashKeys)
|
||||
{
|
||||
//Why "absolete path"?
|
||||
//if (!Path.IsPathRooted(element.Value)) throw new IOException(string.Format("Error in DataPro.Config. {0} must be absolete path", element.Value));
|
||||
|
||||
var info = new DirectoryInfo(element.Value);
|
||||
if (!info.Exists) throw new IOException(string.Format("Plugin directory does not exist: {0}", element.Value));
|
||||
|
||||
PluginCatalog.Catalogs.Add(new DirectoryCatalog(element.Value));
|
||||
}
|
||||
|
||||
// Create MEF container
|
||||
PluginContainer = new CompositionContainer(PluginCatalog);
|
||||
|
||||
foreach (var catalog in PluginCatalog.Catalogs)
|
||||
{
|
||||
var directoryCatalog = catalog as DirectoryCatalog;
|
||||
if (directoryCatalog == null) continue;
|
||||
|
||||
var pluginDir = directoryCatalog.FullPath;
|
||||
|
||||
var files = (new DirectoryInfo(pluginDir)).GetFiles("*.dll");
|
||||
|
||||
foreach (var assembly in files)
|
||||
{
|
||||
var assemblyName = string.Format("{0}{1}", pluginDir, assembly.Name);
|
||||
|
||||
// verift assembly exists and matches requested paramaters
|
||||
if (!File.Exists(assemblyName)) continue;
|
||||
|
||||
var info = AssemblyName.GetAssemblyName(assemblyName);
|
||||
|
||||
// NOTE: sometimes args.Name only has short assembly name, sometimes full name with public key and version
|
||||
//if (info == null || (info.FullName != args.Name && (info.Name != args.Name)))
|
||||
//{
|
||||
// continue;
|
||||
//}
|
||||
|
||||
// Load assembly
|
||||
var asm = Assembly.LoadFrom(assemblyName);
|
||||
if (asm == null) continue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public List<Assembly> GetPluginList<T>() where T : class
|
||||
{
|
||||
var manager = GetPluginManager();
|
||||
foreach (var catalog in manager.PluginCatalog.Catalogs)
|
||||
{
|
||||
var directoryCatalog = catalog as DirectoryCatalog;
|
||||
if (directoryCatalog == null) continue;
|
||||
return directoryCatalog.Parts.Select(part => ReflectionModelServices.GetPartType(part).Value.Assembly).Distinct().ToList();
|
||||
|
||||
}
|
||||
//return export != null ? export.Value : null;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns MEF plugin of type t
|
||||
/// Throws error if no type exported by plugin or more than one plugin has exported type
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type to get</typeparam>
|
||||
/// <returns>reference to type t from MEF plugin</returns>
|
||||
public static T GetPlugin<T>() where T : class
|
||||
{
|
||||
var export = GetPluginManager().PluginContainer.GetExport<T>();
|
||||
return export != null ? export.Value : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns MEF plugin of type T from a collection of plugins that export the same type
|
||||
/// </summary>
|
||||
/// <typeparam name="T">exported type implemented by potentially multiple plugins</typeparam>
|
||||
/// <param name="configPluginSetting">string that tells us which specific plugin we want</param>
|
||||
/// <returns>type T</returns>
|
||||
public static T GetPlugin<T>(string configPluginSetting) where T : class
|
||||
{
|
||||
var result = new Lazy<T>();
|
||||
var manager = GetPluginManager();
|
||||
var plugins = manager.PluginContainer.GetExports<T>();
|
||||
|
||||
//loop through plugins returned and get the specific one we're looking for
|
||||
foreach (var item in plugins)
|
||||
{
|
||||
if (item.Value.ToString() == configPluginSetting)
|
||||
{
|
||||
result = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result.Value;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns list of MEF plugins that export type t
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type to get</typeparam>
|
||||
/// <returns>list of references to type t from MEF plugins</returns>
|
||||
public static IEnumerable<Lazy<T>> GetPlugins<T>() where T : class
|
||||
{
|
||||
var manager = GetPluginManager();
|
||||
return manager.PluginContainer.GetExports<T>();
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns static singleton reference to plugin manager class
|
||||
/// </summary>
|
||||
/// <returns>plugin class</returns>
|
||||
public static PluginManager GetPluginManager()
|
||||
{
|
||||
lock (ThreadLock)
|
||||
{
|
||||
return _pluginManager ?? (_pluginManager = new PluginManager());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This event triggered if system can't find plugin dependancies
|
||||
/// CurrentDomain_AssemblyResolve can search through list of directories instead of just one
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
|
||||
{
|
||||
foreach (var catalog in PluginCatalog.Catalogs)
|
||||
{
|
||||
var directoryCatalog = catalog as DirectoryCatalog;
|
||||
if (directoryCatalog == null) continue;
|
||||
|
||||
var pluginDir = directoryCatalog.FullPath;
|
||||
|
||||
// get name of assembly
|
||||
var baseName = args.Name.Split(new[] { ',' })[0];
|
||||
var assemblyName = string.Format("{0}\\{1}.dll", pluginDir, baseName);
|
||||
|
||||
// verift assembly exists and matches requested paramaters
|
||||
if (!File.Exists(assemblyName)) continue;
|
||||
|
||||
var info = AssemblyName.GetAssemblyName(assemblyName);
|
||||
|
||||
// NOTE: sometimes args.Name only has short assembly name, sometimes full name with public key and version
|
||||
if (info == null || (info.FullName != args.Name && (info.Name != args.Name)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Load assembly
|
||||
var asm = Assembly.LoadFrom(assemblyName);
|
||||
if (asm == null) continue;
|
||||
|
||||
return asm;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace DataPro.Core
|
||||
{
|
||||
public static class DataProConstants
|
||||
{
|
||||
//public const string CustomConfigPath = @"C:\Program Files\DataPro\bin\DataPro.config";
|
||||
public const string CustomConfigPath = @"DataPRO.exe.config";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DataPro.Core.ServiceManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Service manager allows a component to publish an implementation of a singleton interface (service) that
|
||||
/// other components can retrieve reference to without knowing who published it
|
||||
/// </summary>
|
||||
public static class ServiceManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Stores all published interfaces
|
||||
/// </summary>
|
||||
private static readonly Dictionary<Type, object> Services = new Dictionary<Type, object>();
|
||||
|
||||
/// <summary>
|
||||
/// Publishes a service
|
||||
/// </summary>
|
||||
/// <typeparam name="T">interface type of service</typeparam>
|
||||
/// <param name="item">implementation of service</param>
|
||||
public static void Publish<T>(T item) where T : class
|
||||
{
|
||||
if (Services.ContainsKey(typeof(T)))
|
||||
{
|
||||
throw new ArgumentException(string.Format("{0}: has already been published", typeof(T).Name));
|
||||
}
|
||||
|
||||
Services.Add(typeof(T), item);
|
||||
SendServicePublishedEvent(typeof(T), true);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Publishes a list of services
|
||||
/// </summary>
|
||||
/// <param name="item">class that will implement all the listed interfaces</param>
|
||||
/// <param name="interfaceList">list of interfaces</param>
|
||||
/// <param name="skipPublishedInterfaces">true to avoid errors on already published interfaces</param>
|
||||
public static void Publish(object item, IEnumerable<Type> interfaceList, bool skipPublishedInterfaces)
|
||||
{
|
||||
foreach (var t in interfaceList)
|
||||
{
|
||||
if (Exists(t))
|
||||
{
|
||||
if (!skipPublishedInterfaces)
|
||||
{
|
||||
// service already published and caller indicated we should error out
|
||||
throw new ArgumentException(string.Format("{0}: has already been published", t.Name));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// service doesn't exist so publish it
|
||||
Services.Add(t, item);
|
||||
SendServicePublishedEvent(t, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if specifed interface has been published, false if not
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type of interface to check</typeparam>
|
||||
/// <returns>true if interface has been published; false if not published</returns>
|
||||
public static bool Exists<T>() where T : class
|
||||
{
|
||||
return Services.ContainsKey(typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if specifed interface has been published, false if not
|
||||
/// </summary>
|
||||
/// <param name="t">type of interface to check</param>
|
||||
/// <returns>true if interface has been published; false if not published</returns>
|
||||
public static bool Exists(Type t)
|
||||
{
|
||||
return Services.ContainsKey(t);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns published service
|
||||
/// </summary>
|
||||
/// <typeparam name="T">interface type of service</typeparam>
|
||||
/// <returns>published service or exception if not currently published</returns>
|
||||
public static T Get<T>() where T : class
|
||||
{
|
||||
if (!Services.ContainsKey(typeof(T)))
|
||||
{
|
||||
throw new ArgumentException(string.Format("{0}: has not been published", typeof(T).Name));
|
||||
}
|
||||
|
||||
return Services[typeof(T)] as T;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears specified service
|
||||
/// </summary>
|
||||
/// <typeparam name="T">interface type of service to clear</typeparam>
|
||||
public static void Clear<T>() where T : class
|
||||
{
|
||||
if (Services.ContainsKey(typeof(T)))
|
||||
{
|
||||
SendServicePublishedEvent(typeof(T), false);
|
||||
Services.Remove(typeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears list of published interfaces
|
||||
/// </summary>
|
||||
/// <param name="interfaceList">list of interfaces to unpublish</param>
|
||||
public static void Clear(IEnumerable<Type> interfaceList)
|
||||
{
|
||||
foreach (var t in interfaceList)
|
||||
{
|
||||
if (!Services.ContainsKey(t)) continue;
|
||||
|
||||
SendServicePublishedEvent(t, false);
|
||||
Services.Remove(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sends a IServicePublishedEvent through the Event Manger to let subscribers know when
|
||||
/// a service is published or unpublished
|
||||
/// </summary>
|
||||
/// <param name="type">type of interface</param>
|
||||
/// <param name="published">true if being published, false if being unpublished</param>
|
||||
private static void SendServicePublishedEvent(Type type, bool published)
|
||||
{
|
||||
EventManager.EventManager.Publish<IServicePublishedEvent>(new ServicePublishedEvent
|
||||
{
|
||||
IsPublished = published,
|
||||
ServiceType = type
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DataPro.Core.ServiceManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Event fired when a service interface is published\unpublished
|
||||
/// </summary>
|
||||
public interface IServicePublishedEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns type of service being published\unpublished
|
||||
/// </summary>
|
||||
Type ServiceType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if Service is being published, false if being unpublished
|
||||
/// </summary>
|
||||
bool IsPublished { get; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
|
||||
namespace DataPro.Core.Config
|
||||
{
|
||||
public static class DataProConfig
|
||||
{
|
||||
private static readonly Configuration Config;
|
||||
|
||||
// static constructor
|
||||
static DataProConfig()
|
||||
{
|
||||
var dataProConfig = new ExeConfigurationFileMap
|
||||
{
|
||||
ExeConfigFilename = DataProConstants.CustomConfigPath
|
||||
};
|
||||
|
||||
Config = ConfigurationManager.OpenMappedExeConfiguration(dataProConfig, ConfigurationUserLevel.None, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Static variable to hold alternate configuration file
|
||||
/// </summary>
|
||||
public static Configuration AltConfig
|
||||
{
|
||||
get { return Config; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Static method to retrieve a setting from config file
|
||||
/// </summary>
|
||||
/// <param name="key">string</param>
|
||||
/// <returns>string</returns>
|
||||
public static string GetAppSetting(string key)
|
||||
{
|
||||
var appSetting = Config.AppSettings.Settings.Cast<KeyValueConfigurationElement>().FirstOrDefault(setting => setting.Key == key);
|
||||
|
||||
return appSetting == null ? String.Empty : appSetting.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Static method to get a section from config file. Used by plugin code to get plugin library section.
|
||||
/// </summary>
|
||||
/// <param name="sectionName">string</param>
|
||||
/// <returns>object</returns>
|
||||
public static object GetSection(string sectionName)
|
||||
{
|
||||
return Config.GetSection(sectionName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
|
||||
namespace DataPro.Core.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// Event arguments describing change to settings collection
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">key type used in collection</typeparam>
|
||||
/// <typeparam name="TItem">value type used in collection</typeparam>
|
||||
public class SettingsChangedEventArgs<TKey, TItem> : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="changeType">type of scenario change</param>
|
||||
public SettingsChangedEventArgs(ChangeSettingType changeType)
|
||||
{
|
||||
ChangeType = changeType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="changeType">change type</param>
|
||||
/// <param name="key">key type used in collection</param>
|
||||
public SettingsChangedEventArgs(ChangeSettingType changeType, TKey key)
|
||||
{
|
||||
ChangeType = changeType;
|
||||
Key = key;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="changeType">change type</param>
|
||||
/// <param name="key">key type used in collection</param>
|
||||
/// <param name="item">value type used in collection</param>
|
||||
public SettingsChangedEventArgs(ChangeSettingType changeType, TKey key, TItem item)
|
||||
{
|
||||
ChangeType = changeType;
|
||||
Key = key;
|
||||
Item = item;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns type of scenario change
|
||||
/// </summary>
|
||||
public ChangeSettingType ChangeType
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// key associated with changed setting
|
||||
/// </summary>
|
||||
public TKey Key
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Value associated with changed settting
|
||||
/// </summary>
|
||||
public TItem Item
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Type of settings changed
|
||||
/// </summary>
|
||||
public enum ChangeSettingType
|
||||
{
|
||||
Add = 0,
|
||||
Remove = 1,
|
||||
Modified = 3,
|
||||
ClearAll = 4
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DataPro.Core.ServiceManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Event fired when a service interface is published\unpublished
|
||||
/// </summary>
|
||||
public class ServicePublishedEvent : IServicePublishedEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns type of service being published\unpublished
|
||||
/// </summary>
|
||||
public Type ServiceType
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if Service is being published, false if being unpublished
|
||||
/// </summary>
|
||||
public bool IsPublished
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
using System.Configuration;
|
||||
|
||||
namespace DataPro.Core.PluginLib
|
||||
{
|
||||
/// <summary>
|
||||
/// Support class that parses data from DataPro.Core.PluginLib.Config configuration section
|
||||
/// </summary>
|
||||
public class PluginConfigSectionHandler : ConfigurationSection
|
||||
{
|
||||
[ConfigurationProperty("PluginFolders")]
|
||||
public FilterHashKeyCollection HashKeys
|
||||
{
|
||||
get { return ((FilterHashKeyCollection)(base["PluginFolders"])); }
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationCollection(typeof(FilterHashElement))]
|
||||
public class FilterHashKeyCollection : ConfigurationElementCollection
|
||||
{
|
||||
protected override ConfigurationElement CreateNewElement()
|
||||
{
|
||||
return new FilterHashElement();
|
||||
}
|
||||
|
||||
protected override object GetElementKey(ConfigurationElement element)
|
||||
{
|
||||
return ((FilterHashElement)(element)).Key;
|
||||
}
|
||||
|
||||
public FilterHashElement this[int idx]
|
||||
{
|
||||
get
|
||||
{
|
||||
return (FilterHashElement)BaseGet(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class FilterHashElement : ConfigurationElement
|
||||
{
|
||||
[ConfigurationProperty("key", DefaultValue = "", IsKey = true, IsRequired = true)]
|
||||
public string Key
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((string)(base["key"]));
|
||||
}
|
||||
set
|
||||
{
|
||||
base["key"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty("value", DefaultValue = "", IsKey = false, IsRequired = false)]
|
||||
public string Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((string)(base["value"]));
|
||||
}
|
||||
set
|
||||
{
|
||||
base["value"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,194 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
|
||||
namespace DataPro.Core.EventManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Delegate used by event listeners
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="item"></param>
|
||||
public delegate void SubscriberCallbackDelegate<in T>(T item) where T : class;
|
||||
|
||||
public delegate void DiagnosticCallbackDelegate(EventDiagnosticType eventType, Type t, object eventData, string listener);
|
||||
|
||||
/// <summary>
|
||||
/// Allows components to publish events without knowing who is listening
|
||||
/// </summary>
|
||||
public static class EventManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Tracks listeners
|
||||
/// </summary>
|
||||
private static readonly Dictionary<Type, List<object>> SubscriberList = new Dictionary<Type, List<object>>();
|
||||
|
||||
/// <summary>
|
||||
/// Tracks diagnostic listeners
|
||||
/// </summary>
|
||||
private static readonly List<DiagnosticCallbackDelegate> DiagnosticList = new List<DiagnosticCallbackDelegate>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Publish an event
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type of event</typeparam>
|
||||
/// <param name="eventData">event listener</param>
|
||||
public static void Publish<T>(T eventData) where T : class
|
||||
{
|
||||
if (!SubscriberList.ContainsKey(typeof(T))) return;
|
||||
|
||||
var listeners = SubscriberList[typeof(T)];
|
||||
|
||||
foreach (var listener in listeners)
|
||||
{
|
||||
var metaData = listener as EventMetaData<T>;
|
||||
if (metaData == null) continue;
|
||||
|
||||
var triggerCallback = true;
|
||||
|
||||
if (metaData.EventFilter != null)
|
||||
{
|
||||
triggerCallback = metaData.EventFilter(eventData);
|
||||
}
|
||||
|
||||
if (triggerCallback)
|
||||
{
|
||||
metaData.Callback(eventData);
|
||||
}
|
||||
|
||||
SendDiagnosticEvent(EventDiagnosticType.PublishEvent, typeof(T), eventData, metaData.EventFilter != null ? metaData.EventFilter.Method : null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subscribe to an event
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type of event</typeparam>
|
||||
/// <param name="listener">event listener</param>
|
||||
public static void Subscribe<T>(SubscriberCallbackDelegate<T> listener) where T : class
|
||||
{
|
||||
Subscribe(listener, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subscribe to an event
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type of event</typeparam>
|
||||
/// <param name="listener">event listener</param>
|
||||
/// <param name="eventFilter">predicate to filter events sent to event listener</param>
|
||||
public static void Subscribe<T>(SubscriberCallbackDelegate<T> listener, Predicate<T> eventFilter) where T : class
|
||||
{
|
||||
if (!SubscriberList.ContainsKey(typeof(T)))
|
||||
{
|
||||
SubscriberList.Add(typeof(T), new List<object>());
|
||||
}
|
||||
|
||||
var listeners = SubscriberList[typeof(T)];
|
||||
|
||||
var metaData = new EventMetaData<T> { Callback = listener, EventFilter = eventFilter };
|
||||
|
||||
listeners.Add(metaData);
|
||||
|
||||
SendDiagnosticEvent(EventDiagnosticType.AddListener, typeof(T), null, listener.Method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows a subscriber to unsubscribe
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type of event</typeparam>
|
||||
/// <param name="listener">event listener</param>
|
||||
public static void UnSubscribe<T>(SubscriberCallbackDelegate<T> listener) where T : class
|
||||
{
|
||||
if (!SubscriberList.ContainsKey(typeof(T))) return;
|
||||
|
||||
var listeners = SubscriberList[typeof(T)];
|
||||
|
||||
listeners.RemoveAll(p =>
|
||||
{
|
||||
var eventMetaData = p as EventMetaData<T>;
|
||||
return eventMetaData != null && eventMetaData.Callback == listener;
|
||||
});
|
||||
|
||||
SendDiagnosticEvent(EventDiagnosticType.RemoveListener, typeof(T), null, listener.Method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all listeners
|
||||
/// </summary>
|
||||
public static void Clear()
|
||||
{
|
||||
SubscriberList.Clear();
|
||||
SendDiagnosticEvent(EventDiagnosticType.RemoveListener, null, null, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add diagnostic listener
|
||||
/// </summary>
|
||||
/// <param name="listener">event listener</param>
|
||||
public static void SubscribeToDiagnosticEvents(DiagnosticCallbackDelegate listener)
|
||||
{
|
||||
DiagnosticList.Add(listener);
|
||||
SendDiagnosticEvent(EventDiagnosticType.AddListenerDiagnostic, null, null, listener.Method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear diagnostic event
|
||||
/// </summary>
|
||||
/// <param name="listener">listener to unsubscribe</param>
|
||||
public static void UnSubscribeToDiagnosticEvents(DiagnosticCallbackDelegate listener)
|
||||
{
|
||||
DiagnosticList.RemoveAll(p => p == listener);
|
||||
SendDiagnosticEvent(EventDiagnosticType.RemoveListenerDiagnostic, null, null, listener.Method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear all diagnostic events
|
||||
/// </summary>
|
||||
public static void ClearDiagnosticEvents()
|
||||
{
|
||||
DiagnosticList.Clear();
|
||||
SendDiagnosticEvent(EventDiagnosticType.RemoveListenerDiagnostic, null, null, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a diagnostic event
|
||||
/// </summary>
|
||||
/// <param name="diagnosticEventType"></param>
|
||||
/// <param name="eventType"></param>
|
||||
/// <param name="eventData"></param>
|
||||
/// <param name="listenerMethod"></param>
|
||||
private static void SendDiagnosticEvent(EventDiagnosticType diagnosticEventType, Type eventType, object eventData, MemberInfo listenerMethod)
|
||||
{
|
||||
foreach (var diagnosticEvent in DiagnosticList)
|
||||
{
|
||||
string listener = null;
|
||||
|
||||
if (listenerMethod != null && listenerMethod.DeclaringType != null)
|
||||
{
|
||||
listener = string.Format("{0}.{1} , {2}", listenerMethod.DeclaringType.FullName, listenerMethod.Name, listenerMethod.DeclaringType.Assembly.FullName);
|
||||
}
|
||||
|
||||
diagnosticEvent(diagnosticEventType, eventType, eventData, listener);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum EventDiagnosticType
|
||||
{
|
||||
AddListener = 0,
|
||||
AddListenerDiagnostic = 1,
|
||||
PublishEvent = 2,
|
||||
RemoveListenerDiagnostic = 3,
|
||||
RemoveListener = 4
|
||||
}
|
||||
|
||||
class EventMetaData<T> where T : class
|
||||
{
|
||||
public Predicate<T> EventFilter { get; set; }
|
||||
public SubscriberCallbackDelegate<T> Callback { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
namespace DataPro.Core.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements a dictionary with events when an item is changed
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">key type</typeparam>
|
||||
/// <typeparam name="TItem">value type</typeparam>
|
||||
/// <history>
|
||||
/// <list type="number">
|
||||
/// <item>{01/22/2014}. {RCD}. {Initial Version}</item>
|
||||
/// </list>
|
||||
/// </history>
|
||||
public class SettingsCollection<TKey, TItem> : IDictionary<TKey, TItem>
|
||||
{
|
||||
/// <summary>
|
||||
/// Event fired when an item changes in dictionary
|
||||
/// </summary>
|
||||
public event EventHandler<SettingsChangedEventArgs<TKey, TItem>> CollectionItemPropertyChanged;
|
||||
|
||||
/// <summary>
|
||||
/// List of stored items
|
||||
/// </summary>
|
||||
private readonly Dictionary<TKey, TItem> _items = new Dictionary<TKey, TItem>();
|
||||
|
||||
|
||||
#region IDictionary
|
||||
|
||||
/// <summary>
|
||||
/// Add item
|
||||
/// </summary>
|
||||
/// <param name="key">key</param>
|
||||
/// <param name="value">value</param>
|
||||
public void Add(TKey key, TItem value)
|
||||
{
|
||||
_items.Add(key, value);
|
||||
FireItemChangedEvent(ChangeSettingType.Add, key, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if item contains key
|
||||
/// </summary>
|
||||
/// <param name="key">key</param>
|
||||
/// <returns>true if key exists</returns>
|
||||
public bool ContainsKey(TKey key)
|
||||
{
|
||||
return _items.ContainsKey(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all keys in collection
|
||||
/// </summary>
|
||||
public ICollection<TKey> Keys
|
||||
{
|
||||
get { return _items.Keys; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes key
|
||||
/// </summary>
|
||||
/// <param name="key">key</param>
|
||||
/// <returns>true if key removed</returns>
|
||||
public bool Remove(TKey key)
|
||||
{
|
||||
var res = _items.Remove(key);
|
||||
if (res) FireItemChangedEvent(ChangeSettingType.Remove, key);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Trys to get specified value
|
||||
/// </summary>
|
||||
/// <param name="key">key</param>
|
||||
/// <param name="value">value if key exists</param>
|
||||
/// <returns>true if key exists; false if it doesn't exist</returns>
|
||||
public bool TryGetValue(TKey key, out TItem value)
|
||||
{
|
||||
return _items.TryGetValue(key, out value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List of values in collection
|
||||
/// </summary>
|
||||
public ICollection<TItem> Values
|
||||
{
|
||||
get { return _items.Values; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets item in collection (overloads [] operator)
|
||||
/// </summary>
|
||||
/// <param name="key">key</param>
|
||||
/// <returns>item in collection</returns>
|
||||
public TItem this[TKey key]
|
||||
{
|
||||
get
|
||||
{
|
||||
return _items[key];
|
||||
}
|
||||
set
|
||||
{
|
||||
_items[key] = value;
|
||||
FireItemChangedEvent(ChangeSettingType.Add, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds new item
|
||||
/// </summary>
|
||||
/// <param name="item">new item to add</param>
|
||||
public void Add(KeyValuePair<TKey, TItem> item)
|
||||
{
|
||||
_items.Add(item.Key, item.Value);
|
||||
FireItemChangedEvent(ChangeSettingType.Add, item.Key, item.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears entire collection
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
_items.Clear();
|
||||
FireItemChangedEvent(ChangeSettingType.ClearAll);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if item is in collection
|
||||
/// </summary>
|
||||
/// <param name="item">item to check</param>
|
||||
/// <returns>true if item exists</returns>
|
||||
public bool Contains(KeyValuePair<TKey, TItem> item)
|
||||
{
|
||||
return _items.ContainsKey(item.Key) && _items.ContainsValue(item.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copys items to array
|
||||
/// </summary>
|
||||
/// <param name="array"></param>
|
||||
/// <param name="arrayIndex"></param>
|
||||
public void CopyTo(KeyValuePair<TKey, TItem>[] array, int arrayIndex)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns count of items
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get { return _items.Count; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if readonly collection
|
||||
/// </summary>
|
||||
public bool IsReadOnly
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes specified item
|
||||
/// </summary>
|
||||
/// <param name="item">item to remove</param>
|
||||
/// <returns>true if item removed</returns>
|
||||
public bool Remove(KeyValuePair<TKey, TItem> item)
|
||||
{
|
||||
var res = _items.Remove(item.Key);
|
||||
if (res) FireItemChangedEvent(ChangeSettingType.Remove, item.Key);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return enumerator for collection
|
||||
/// </summary>
|
||||
/// <returns>enumerator</returns>
|
||||
public IEnumerator<KeyValuePair<TKey, TItem>> GetEnumerator()
|
||||
{
|
||||
return _items.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return enumerator for collection
|
||||
/// </summary>
|
||||
/// <returns>enumerator</returns>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return _items.GetEnumerator();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private methods
|
||||
|
||||
/// <summary>
|
||||
/// Fires collection change event
|
||||
/// </summary>
|
||||
/// <param name="changeType">type of change</param>
|
||||
private void FireItemChangedEvent(ChangeSettingType changeType)
|
||||
{
|
||||
if (CollectionItemPropertyChanged != null)
|
||||
{
|
||||
CollectionItemPropertyChanged(this, new SettingsChangedEventArgs<TKey, TItem>(changeType));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires collection change event
|
||||
/// </summary>
|
||||
/// <param name="changeType">type of change</param>
|
||||
/// <param name="key">key</param>
|
||||
private void FireItemChangedEvent(ChangeSettingType changeType, TKey key)
|
||||
{
|
||||
if (CollectionItemPropertyChanged != null)
|
||||
{
|
||||
CollectionItemPropertyChanged(this, new SettingsChangedEventArgs<TKey, TItem>(changeType, key));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires collection change event
|
||||
/// </summary>
|
||||
/// <param name="changeType">type of change</param>
|
||||
/// <param name="key">key</param>
|
||||
/// <param name="item">item</param>
|
||||
private void FireItemChangedEvent(ChangeSettingType changeType, TKey key, TItem item)
|
||||
{
|
||||
if (CollectionItemPropertyChanged != null)
|
||||
{
|
||||
CollectionItemPropertyChanged(this, new SettingsChangedEventArgs<TKey, TItem>(changeType, key, item));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
|
||||
</configuration>
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace DataPro.Core.PluginLib
|
||||
{
|
||||
/// <summary>
|
||||
/// Support class that stores data de-serialized from DatPro.Core.PluginLib.Config in App.Config configuration section
|
||||
/// </summary>
|
||||
[XmlRoot(ElementName = "DatPro.Core.PluginLib.Config")]
|
||||
public class PluginConfigData
|
||||
{
|
||||
[XmlArrayItem("Folder")]
|
||||
public string[] PluginFolders;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{FAB1F470-1574-4301-B56E-D3364AA93679}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>DataPro.Core</RootNamespace>
|
||||
<AssemblyName>DataPro.Core</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SccProjectName>SAK</SccProjectName>
|
||||
<SccLocalPath>SAK</SccLocalPath>
|
||||
<SccAuxPath>SAK</SccAuxPath>
|
||||
<SccProvider>SAK</SccProvider>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Config\DataProConfig.cs" />
|
||||
<Compile Include="DataProConstants.cs" />
|
||||
<Compile Include="EventManager\EventManager.cs" />
|
||||
<Compile Include="PluginLib\PluginConfig.cs" />
|
||||
<Compile Include="PluginLib\PluginConfigData.cs" />
|
||||
<Compile Include="PluginLib\PluginConfigSectionHandler.cs" />
|
||||
<Compile Include="PluginLib\PluginManager.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ServiceManager\IServicePublishedEvent.cs" />
|
||||
<Compile Include="ServiceManager\ServiceManager.cs" />
|
||||
<Compile Include="ServiceManager\ServicePublishedEvent.cs" />
|
||||
<Compile Include="Settings\SettingsChangedEventArgs.cs" />
|
||||
<Compile Include="Settings\SettingsCollection.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Common\DTS.Common.csproj">
|
||||
<Project>{114edc77-f3b5-4576-a91b-40818d503b55}</Project>
|
||||
<Name>DTS.Common</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="RegionAdapters\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using DataPro.Core.Config;
|
||||
|
||||
namespace DataPro.Core.PluginLib
|
||||
{
|
||||
/// <summary>
|
||||
/// Static class used to store plugin configuration info
|
||||
/// </summary>
|
||||
public static class PluginConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// name of setting to look in config for equipment database
|
||||
/// </summary>
|
||||
public const string DataProPlugins = "dataProPlugins";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// concatenate plugin name from app setting with class exporter name for dataPro plugins
|
||||
/// </summary>
|
||||
/// <param name="setting"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetDataProPluginsSetting(string setting)
|
||||
{
|
||||
return DataProConfig.GetAppSetting(DataProPlugins) + "." + setting;
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
DataPRO/DataPRO.Core/.svn/wc.db
Normal file
BIN
DataPRO/DataPRO.Core/.svn/wc.db
Normal file
Binary file not shown.
0
DataPRO/DataPRO.Core/.svn/wc.db-journal
Normal file
0
DataPRO/DataPRO.Core/.svn/wc.db-journal
Normal file
4
DataPRO/DataPRO.Core/App.config
Normal file
4
DataPRO/DataPRO.Core/App.config
Normal file
@@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
|
||||
</configuration>
|
||||
52
DataPRO/DataPRO.Core/Config/DataProConfig.cs
Normal file
52
DataPRO/DataPRO.Core/Config/DataProConfig.cs
Normal file
@@ -0,0 +1,52 @@
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
|
||||
namespace DataPro.Core.Config
|
||||
{
|
||||
public static class DataProConfig
|
||||
{
|
||||
private static readonly Configuration Config;
|
||||
|
||||
// static constructor
|
||||
static DataProConfig()
|
||||
{
|
||||
var dataProConfig = new ExeConfigurationFileMap
|
||||
{
|
||||
ExeConfigFilename = DataProConstants.CustomConfigPath
|
||||
};
|
||||
|
||||
Config = ConfigurationManager.OpenMappedExeConfiguration(dataProConfig, ConfigurationUserLevel.None, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Static variable to hold alternate configuration file
|
||||
/// </summary>
|
||||
public static Configuration AltConfig
|
||||
{
|
||||
get { return Config; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Static method to retrieve a setting from config file
|
||||
/// </summary>
|
||||
/// <param name="key">string</param>
|
||||
/// <returns>string</returns>
|
||||
public static string GetAppSetting(string key)
|
||||
{
|
||||
var appSetting = Config.AppSettings.Settings.Cast<KeyValueConfigurationElement>().FirstOrDefault(setting => setting.Key == key);
|
||||
|
||||
return appSetting == null ? String.Empty : appSetting.Value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Static method to get a section from config file. Used by plugin code to get plugin library section.
|
||||
/// </summary>
|
||||
/// <param name="sectionName">string</param>
|
||||
/// <returns>object</returns>
|
||||
public static object GetSection(string sectionName)
|
||||
{
|
||||
return Config.GetSection(sectionName);
|
||||
}
|
||||
}
|
||||
}
|
||||
65
DataPRO/DataPRO.Core/DataPro.Core.csproj
Normal file
65
DataPRO/DataPRO.Core/DataPro.Core.csproj
Normal file
@@ -0,0 +1,65 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{FAB1F470-1574-4301-B56E-D3364AA93679}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>DataPro.Core</RootNamespace>
|
||||
<AssemblyName>DataPro.Core</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<SccProjectName>SAK</SccProjectName>
|
||||
<SccLocalPath>SAK</SccLocalPath>
|
||||
<SccAuxPath>SAK</SccAuxPath>
|
||||
<SccProvider>SAK</SccProvider>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.ComponentModel.Composition" />
|
||||
<Reference Include="System.Configuration" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Config\DataProConfig.cs" />
|
||||
<Compile Include="DataProConstants.cs" />
|
||||
<Compile Include="EventManager\EventManager.cs" />
|
||||
<Compile Include="PluginLib\PluginConfig.cs" />
|
||||
<Compile Include="PluginLib\PluginConfigData.cs" />
|
||||
<Compile Include="PluginLib\PluginConfigSectionHandler.cs" />
|
||||
<Compile Include="PluginLib\PluginManager.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="ServiceManager\IServicePublishedEvent.cs" />
|
||||
<Compile Include="ServiceManager\ServiceManager.cs" />
|
||||
<Compile Include="ServiceManager\ServicePublishedEvent.cs" />
|
||||
<Compile Include="Settings\SettingsChangedEventArgs.cs" />
|
||||
<Compile Include="Settings\SettingsCollection.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Common\DTS.Common.csproj">
|
||||
<Project>{114edc77-f3b5-4576-a91b-40818d503b55}</Project>
|
||||
<Name>DTS.Common</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="RegionAdapters\" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
|
||||
Other similar extension points exist, see Microsoft.Common.targets.
|
||||
<Target Name="BeforeBuild">
|
||||
</Target>
|
||||
<Target Name="AfterBuild">
|
||||
</Target>
|
||||
-->
|
||||
</Project>
|
||||
8
DataPRO/DataPRO.Core/DataProConstants.cs
Normal file
8
DataPRO/DataPRO.Core/DataProConstants.cs
Normal file
@@ -0,0 +1,8 @@
|
||||
namespace DataPro.Core
|
||||
{
|
||||
public static class DataProConstants
|
||||
{
|
||||
//public const string CustomConfigPath = @"C:\Program Files\DataPro\bin\DataPro.config";
|
||||
public const string CustomConfigPath = @"DataPRO.exe.config";
|
||||
}
|
||||
}
|
||||
194
DataPRO/DataPRO.Core/EventManager/EventManager.cs
Normal file
194
DataPRO/DataPRO.Core/EventManager/EventManager.cs
Normal file
@@ -0,0 +1,194 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
|
||||
namespace DataPro.Core.EventManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Delegate used by event listeners
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="item"></param>
|
||||
public delegate void SubscriberCallbackDelegate<in T>(T item) where T : class;
|
||||
|
||||
public delegate void DiagnosticCallbackDelegate(EventDiagnosticType eventType, Type t, object eventData, string listener);
|
||||
|
||||
/// <summary>
|
||||
/// Allows components to publish events without knowing who is listening
|
||||
/// </summary>
|
||||
public static class EventManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Tracks listeners
|
||||
/// </summary>
|
||||
private static readonly Dictionary<Type, List<object>> SubscriberList = new Dictionary<Type, List<object>>();
|
||||
|
||||
/// <summary>
|
||||
/// Tracks diagnostic listeners
|
||||
/// </summary>
|
||||
private static readonly List<DiagnosticCallbackDelegate> DiagnosticList = new List<DiagnosticCallbackDelegate>();
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Publish an event
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type of event</typeparam>
|
||||
/// <param name="eventData">event listener</param>
|
||||
public static void Publish<T>(T eventData) where T : class
|
||||
{
|
||||
if (!SubscriberList.ContainsKey(typeof(T))) return;
|
||||
|
||||
var listeners = SubscriberList[typeof(T)];
|
||||
|
||||
foreach (var listener in listeners)
|
||||
{
|
||||
var metaData = listener as EventMetaData<T>;
|
||||
if (metaData == null) continue;
|
||||
|
||||
var triggerCallback = true;
|
||||
|
||||
if (metaData.EventFilter != null)
|
||||
{
|
||||
triggerCallback = metaData.EventFilter(eventData);
|
||||
}
|
||||
|
||||
if (triggerCallback)
|
||||
{
|
||||
metaData.Callback(eventData);
|
||||
}
|
||||
|
||||
SendDiagnosticEvent(EventDiagnosticType.PublishEvent, typeof(T), eventData, metaData.EventFilter != null ? metaData.EventFilter.Method : null);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subscribe to an event
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type of event</typeparam>
|
||||
/// <param name="listener">event listener</param>
|
||||
public static void Subscribe<T>(SubscriberCallbackDelegate<T> listener) where T : class
|
||||
{
|
||||
Subscribe(listener, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Subscribe to an event
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type of event</typeparam>
|
||||
/// <param name="listener">event listener</param>
|
||||
/// <param name="eventFilter">predicate to filter events sent to event listener</param>
|
||||
public static void Subscribe<T>(SubscriberCallbackDelegate<T> listener, Predicate<T> eventFilter) where T : class
|
||||
{
|
||||
if (!SubscriberList.ContainsKey(typeof(T)))
|
||||
{
|
||||
SubscriberList.Add(typeof(T), new List<object>());
|
||||
}
|
||||
|
||||
var listeners = SubscriberList[typeof(T)];
|
||||
|
||||
var metaData = new EventMetaData<T> { Callback = listener, EventFilter = eventFilter };
|
||||
|
||||
listeners.Add(metaData);
|
||||
|
||||
SendDiagnosticEvent(EventDiagnosticType.AddListener, typeof(T), null, listener.Method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows a subscriber to unsubscribe
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type of event</typeparam>
|
||||
/// <param name="listener">event listener</param>
|
||||
public static void UnSubscribe<T>(SubscriberCallbackDelegate<T> listener) where T : class
|
||||
{
|
||||
if (!SubscriberList.ContainsKey(typeof(T))) return;
|
||||
|
||||
var listeners = SubscriberList[typeof(T)];
|
||||
|
||||
listeners.RemoveAll(p =>
|
||||
{
|
||||
var eventMetaData = p as EventMetaData<T>;
|
||||
return eventMetaData != null && eventMetaData.Callback == listener;
|
||||
});
|
||||
|
||||
SendDiagnosticEvent(EventDiagnosticType.RemoveListener, typeof(T), null, listener.Method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all listeners
|
||||
/// </summary>
|
||||
public static void Clear()
|
||||
{
|
||||
SubscriberList.Clear();
|
||||
SendDiagnosticEvent(EventDiagnosticType.RemoveListener, null, null, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add diagnostic listener
|
||||
/// </summary>
|
||||
/// <param name="listener">event listener</param>
|
||||
public static void SubscribeToDiagnosticEvents(DiagnosticCallbackDelegate listener)
|
||||
{
|
||||
DiagnosticList.Add(listener);
|
||||
SendDiagnosticEvent(EventDiagnosticType.AddListenerDiagnostic, null, null, listener.Method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear diagnostic event
|
||||
/// </summary>
|
||||
/// <param name="listener">listener to unsubscribe</param>
|
||||
public static void UnSubscribeToDiagnosticEvents(DiagnosticCallbackDelegate listener)
|
||||
{
|
||||
DiagnosticList.RemoveAll(p => p == listener);
|
||||
SendDiagnosticEvent(EventDiagnosticType.RemoveListenerDiagnostic, null, null, listener.Method);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear all diagnostic events
|
||||
/// </summary>
|
||||
public static void ClearDiagnosticEvents()
|
||||
{
|
||||
DiagnosticList.Clear();
|
||||
SendDiagnosticEvent(EventDiagnosticType.RemoveListenerDiagnostic, null, null, null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sends a diagnostic event
|
||||
/// </summary>
|
||||
/// <param name="diagnosticEventType"></param>
|
||||
/// <param name="eventType"></param>
|
||||
/// <param name="eventData"></param>
|
||||
/// <param name="listenerMethod"></param>
|
||||
private static void SendDiagnosticEvent(EventDiagnosticType diagnosticEventType, Type eventType, object eventData, MemberInfo listenerMethod)
|
||||
{
|
||||
foreach (var diagnosticEvent in DiagnosticList)
|
||||
{
|
||||
string listener = null;
|
||||
|
||||
if (listenerMethod != null && listenerMethod.DeclaringType != null)
|
||||
{
|
||||
listener = string.Format("{0}.{1} , {2}", listenerMethod.DeclaringType.FullName, listenerMethod.Name, listenerMethod.DeclaringType.Assembly.FullName);
|
||||
}
|
||||
|
||||
diagnosticEvent(diagnosticEventType, eventType, eventData, listener);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public enum EventDiagnosticType
|
||||
{
|
||||
AddListener = 0,
|
||||
AddListenerDiagnostic = 1,
|
||||
PublishEvent = 2,
|
||||
RemoveListenerDiagnostic = 3,
|
||||
RemoveListener = 4
|
||||
}
|
||||
|
||||
class EventMetaData<T> where T : class
|
||||
{
|
||||
public Predicate<T> EventFilter { get; set; }
|
||||
public SubscriberCallbackDelegate<T> Callback { get; set; }
|
||||
}
|
||||
|
||||
}
|
||||
31
DataPRO/DataPRO.Core/PluginLib/PluginConfig.cs
Normal file
31
DataPRO/DataPRO.Core/PluginLib/PluginConfig.cs
Normal file
@@ -0,0 +1,31 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using DataPro.Core.Config;
|
||||
|
||||
namespace DataPro.Core.PluginLib
|
||||
{
|
||||
/// <summary>
|
||||
/// Static class used to store plugin configuration info
|
||||
/// </summary>
|
||||
public static class PluginConfig
|
||||
{
|
||||
/// <summary>
|
||||
/// name of setting to look in config for equipment database
|
||||
/// </summary>
|
||||
public const string DataProPlugins = "dataProPlugins";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// concatenate plugin name from app setting with class exporter name for dataPro plugins
|
||||
/// </summary>
|
||||
/// <param name="setting"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetDataProPluginsSetting(string setting)
|
||||
{
|
||||
return DataProConfig.GetAppSetting(DataProPlugins) + "." + setting;
|
||||
}
|
||||
}
|
||||
}
|
||||
14
DataPRO/DataPRO.Core/PluginLib/PluginConfigData.cs
Normal file
14
DataPRO/DataPRO.Core/PluginLib/PluginConfigData.cs
Normal file
@@ -0,0 +1,14 @@
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace DataPro.Core.PluginLib
|
||||
{
|
||||
/// <summary>
|
||||
/// Support class that stores data de-serialized from DatPro.Core.PluginLib.Config in App.Config configuration section
|
||||
/// </summary>
|
||||
[XmlRoot(ElementName = "DatPro.Core.PluginLib.Config")]
|
||||
public class PluginConfigData
|
||||
{
|
||||
[XmlArrayItem("Folder")]
|
||||
public string[] PluginFolders;
|
||||
}
|
||||
}
|
||||
67
DataPRO/DataPRO.Core/PluginLib/PluginConfigSectionHandler.cs
Normal file
67
DataPRO/DataPRO.Core/PluginLib/PluginConfigSectionHandler.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using System.Configuration;
|
||||
|
||||
namespace DataPro.Core.PluginLib
|
||||
{
|
||||
/// <summary>
|
||||
/// Support class that parses data from DataPro.Core.PluginLib.Config configuration section
|
||||
/// </summary>
|
||||
public class PluginConfigSectionHandler : ConfigurationSection
|
||||
{
|
||||
[ConfigurationProperty("PluginFolders")]
|
||||
public FilterHashKeyCollection HashKeys
|
||||
{
|
||||
get { return ((FilterHashKeyCollection)(base["PluginFolders"])); }
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationCollection(typeof(FilterHashElement))]
|
||||
public class FilterHashKeyCollection : ConfigurationElementCollection
|
||||
{
|
||||
protected override ConfigurationElement CreateNewElement()
|
||||
{
|
||||
return new FilterHashElement();
|
||||
}
|
||||
|
||||
protected override object GetElementKey(ConfigurationElement element)
|
||||
{
|
||||
return ((FilterHashElement)(element)).Key;
|
||||
}
|
||||
|
||||
public FilterHashElement this[int idx]
|
||||
{
|
||||
get
|
||||
{
|
||||
return (FilterHashElement)BaseGet(idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class FilterHashElement : ConfigurationElement
|
||||
{
|
||||
[ConfigurationProperty("key", DefaultValue = "", IsKey = true, IsRequired = true)]
|
||||
public string Key
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((string)(base["key"]));
|
||||
}
|
||||
set
|
||||
{
|
||||
base["key"] = value;
|
||||
}
|
||||
}
|
||||
|
||||
[ConfigurationProperty("value", DefaultValue = "", IsKey = false, IsRequired = false)]
|
||||
public string Value
|
||||
{
|
||||
get
|
||||
{
|
||||
return ((string)(base["value"]));
|
||||
}
|
||||
set
|
||||
{
|
||||
base["value"] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
216
DataPRO/DataPRO.Core/PluginLib/PluginManager.cs
Normal file
216
DataPRO/DataPRO.Core/PluginLib/PluginManager.cs
Normal file
@@ -0,0 +1,216 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.IO;
|
||||
using System.ComponentModel.Composition.Hosting;
|
||||
using System.ComponentModel.Composition.ReflectionModel;
|
||||
using System.Linq;
|
||||
using DataPro.Core.Config;
|
||||
|
||||
namespace DataPro.Core.PluginLib
|
||||
{
|
||||
/// <summary>
|
||||
/// PluginManager class to manage MEF plugins
|
||||
/// NOTE: This class has to be thread safe
|
||||
/// </summary>
|
||||
public class PluginManager
|
||||
{
|
||||
// reference to singleton plugin manager
|
||||
private static PluginManager _pluginManager;
|
||||
|
||||
/// <summary>
|
||||
/// MEF catalog
|
||||
/// </summary>
|
||||
private AggregateCatalog PluginCatalog { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// MEF container
|
||||
/// </summary>
|
||||
private CompositionContainer PluginContainer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Thread lock
|
||||
/// </summary>
|
||||
private static readonly object ThreadLock = new object();
|
||||
|
||||
/// <summary>
|
||||
/// Constructor that intializes catalog and container
|
||||
/// </summary>
|
||||
private PluginManager()
|
||||
{
|
||||
// Create MEF catalog
|
||||
PluginCatalog = new AggregateCatalog();
|
||||
//PluginCatalog = new AggregateCatalog(new AssemblyCatalog(typeof(MediaTypeNames.Application).Assembly));
|
||||
|
||||
// Get plugin folder from App.Config;
|
||||
var pcsh = (PluginConfigSectionHandler)DataProConfig.GetSection("DataPro.Core.PluginLib.Config");
|
||||
if (pcsh == null) throw new Exception("Unable to retrieve plugin config data from DataPro.config (DataPro.Core.PluginLib.Config)");
|
||||
|
||||
|
||||
foreach (FilterHashElement element in pcsh.HashKeys)
|
||||
{
|
||||
//Why "absolete path"?
|
||||
//if (!Path.IsPathRooted(element.Value)) throw new IOException(string.Format("Error in DataPro.Config. {0} must be absolete path", element.Value));
|
||||
|
||||
var info = new DirectoryInfo(element.Value);
|
||||
if (!info.Exists) throw new IOException(string.Format("Plugin directory does not exist: {0}", element.Value));
|
||||
|
||||
PluginCatalog.Catalogs.Add(new DirectoryCatalog(element.Value));
|
||||
}
|
||||
|
||||
// Create MEF container
|
||||
PluginContainer = new CompositionContainer(PluginCatalog);
|
||||
|
||||
foreach (var catalog in PluginCatalog.Catalogs)
|
||||
{
|
||||
var directoryCatalog = catalog as DirectoryCatalog;
|
||||
if (directoryCatalog == null) continue;
|
||||
|
||||
var pluginDir = directoryCatalog.FullPath;
|
||||
|
||||
var files = (new DirectoryInfo(pluginDir)).GetFiles("*.dll");
|
||||
|
||||
foreach (var assembly in files)
|
||||
{
|
||||
var assemblyName = string.Format("{0}{1}", pluginDir, assembly.Name);
|
||||
|
||||
// verift assembly exists and matches requested paramaters
|
||||
if (!File.Exists(assemblyName)) continue;
|
||||
|
||||
var info = AssemblyName.GetAssemblyName(assemblyName);
|
||||
|
||||
// NOTE: sometimes args.Name only has short assembly name, sometimes full name with public key and version
|
||||
//if (info == null || (info.FullName != args.Name && (info.Name != args.Name)))
|
||||
//{
|
||||
// continue;
|
||||
//}
|
||||
|
||||
// Load assembly
|
||||
var asm = Assembly.LoadFrom(assemblyName);
|
||||
if (asm == null) continue;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
public List<Assembly> GetPluginList<T>() where T : class
|
||||
{
|
||||
var manager = GetPluginManager();
|
||||
foreach (var catalog in manager.PluginCatalog.Catalogs)
|
||||
{
|
||||
var directoryCatalog = catalog as DirectoryCatalog;
|
||||
if (directoryCatalog == null) continue;
|
||||
return directoryCatalog.Parts.Select(part => ReflectionModelServices.GetPartType(part).Value.Assembly).Distinct().ToList();
|
||||
|
||||
}
|
||||
//return export != null ? export.Value : null;
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns MEF plugin of type t
|
||||
/// Throws error if no type exported by plugin or more than one plugin has exported type
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type to get</typeparam>
|
||||
/// <returns>reference to type t from MEF plugin</returns>
|
||||
public static T GetPlugin<T>() where T : class
|
||||
{
|
||||
var export = GetPluginManager().PluginContainer.GetExport<T>();
|
||||
return export != null ? export.Value : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns MEF plugin of type T from a collection of plugins that export the same type
|
||||
/// </summary>
|
||||
/// <typeparam name="T">exported type implemented by potentially multiple plugins</typeparam>
|
||||
/// <param name="configPluginSetting">string that tells us which specific plugin we want</param>
|
||||
/// <returns>type T</returns>
|
||||
public static T GetPlugin<T>(string configPluginSetting) where T : class
|
||||
{
|
||||
var result = new Lazy<T>();
|
||||
var manager = GetPluginManager();
|
||||
var plugins = manager.PluginContainer.GetExports<T>();
|
||||
|
||||
//loop through plugins returned and get the specific one we're looking for
|
||||
foreach (var item in plugins)
|
||||
{
|
||||
if (item.Value.ToString() == configPluginSetting)
|
||||
{
|
||||
result = item;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result.Value;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Returns list of MEF plugins that export type t
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type to get</typeparam>
|
||||
/// <returns>list of references to type t from MEF plugins</returns>
|
||||
public static IEnumerable<Lazy<T>> GetPlugins<T>() where T : class
|
||||
{
|
||||
var manager = GetPluginManager();
|
||||
return manager.PluginContainer.GetExports<T>();
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns static singleton reference to plugin manager class
|
||||
/// </summary>
|
||||
/// <returns>plugin class</returns>
|
||||
public static PluginManager GetPluginManager()
|
||||
{
|
||||
lock (ThreadLock)
|
||||
{
|
||||
return _pluginManager ?? (_pluginManager = new PluginManager());
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This event triggered if system can't find plugin dependancies
|
||||
/// CurrentDomain_AssemblyResolve can search through list of directories instead of just one
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="args"></param>
|
||||
/// <returns></returns>
|
||||
private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
|
||||
{
|
||||
foreach (var catalog in PluginCatalog.Catalogs)
|
||||
{
|
||||
var directoryCatalog = catalog as DirectoryCatalog;
|
||||
if (directoryCatalog == null) continue;
|
||||
|
||||
var pluginDir = directoryCatalog.FullPath;
|
||||
|
||||
// get name of assembly
|
||||
var baseName = args.Name.Split(new[] { ',' })[0];
|
||||
var assemblyName = string.Format("{0}\\{1}.dll", pluginDir, baseName);
|
||||
|
||||
// verift assembly exists and matches requested paramaters
|
||||
if (!File.Exists(assemblyName)) continue;
|
||||
|
||||
var info = AssemblyName.GetAssemblyName(assemblyName);
|
||||
|
||||
// NOTE: sometimes args.Name only has short assembly name, sometimes full name with public key and version
|
||||
if (info == null || (info.FullName != args.Name && (info.Name != args.Name)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Load assembly
|
||||
var asm = Assembly.LoadFrom(assemblyName);
|
||||
if (asm == null) continue;
|
||||
|
||||
return asm;
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
36
DataPRO/DataPRO.Core/Properties/AssemblyInfo.cs
Normal file
36
DataPRO/DataPRO.Core/Properties/AssemblyInfo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// General Information about an assembly is controlled through the following
|
||||
// set of attributes. Change these attribute values to modify the information
|
||||
// associated with an assembly.
|
||||
[assembly: AssemblyTitle("DataPro.Core")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("DataPro.Core")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2016")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// Setting ComVisible to false makes the types in this assembly not visible
|
||||
// to COM components. If you need to access a type in this assembly from
|
||||
// COM, set the ComVisible attribute to true on that type.
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// The following GUID is for the ID of the typelib if this project is exposed to COM
|
||||
[assembly: Guid("bdf5ad7a-51db-4ad0-8186-d1ead7405848")]
|
||||
|
||||
// Version information for an assembly consists of the following four values:
|
||||
//
|
||||
// Major Version
|
||||
// Minor Version
|
||||
// Build Number
|
||||
// Revision
|
||||
//
|
||||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DataPro.Core.ServiceManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Event fired when a service interface is published\unpublished
|
||||
/// </summary>
|
||||
public interface IServicePublishedEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns type of service being published\unpublished
|
||||
/// </summary>
|
||||
Type ServiceType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if Service is being published, false if being unpublished
|
||||
/// </summary>
|
||||
bool IsPublished { get; }
|
||||
}
|
||||
}
|
||||
143
DataPRO/DataPRO.Core/ServiceManager/ServiceManager.cs
Normal file
143
DataPRO/DataPRO.Core/ServiceManager/ServiceManager.cs
Normal file
@@ -0,0 +1,143 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DataPro.Core.ServiceManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Service manager allows a component to publish an implementation of a singleton interface (service) that
|
||||
/// other components can retrieve reference to without knowing who published it
|
||||
/// </summary>
|
||||
public static class ServiceManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Stores all published interfaces
|
||||
/// </summary>
|
||||
private static readonly Dictionary<Type, object> Services = new Dictionary<Type, object>();
|
||||
|
||||
/// <summary>
|
||||
/// Publishes a service
|
||||
/// </summary>
|
||||
/// <typeparam name="T">interface type of service</typeparam>
|
||||
/// <param name="item">implementation of service</param>
|
||||
public static void Publish<T>(T item) where T : class
|
||||
{
|
||||
if (Services.ContainsKey(typeof(T)))
|
||||
{
|
||||
throw new ArgumentException(string.Format("{0}: has already been published", typeof(T).Name));
|
||||
}
|
||||
|
||||
Services.Add(typeof(T), item);
|
||||
SendServicePublishedEvent(typeof(T), true);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Publishes a list of services
|
||||
/// </summary>
|
||||
/// <param name="item">class that will implement all the listed interfaces</param>
|
||||
/// <param name="interfaceList">list of interfaces</param>
|
||||
/// <param name="skipPublishedInterfaces">true to avoid errors on already published interfaces</param>
|
||||
public static void Publish(object item, IEnumerable<Type> interfaceList, bool skipPublishedInterfaces)
|
||||
{
|
||||
foreach (var t in interfaceList)
|
||||
{
|
||||
if (Exists(t))
|
||||
{
|
||||
if (!skipPublishedInterfaces)
|
||||
{
|
||||
// service already published and caller indicated we should error out
|
||||
throw new ArgumentException(string.Format("{0}: has already been published", t.Name));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// service doesn't exist so publish it
|
||||
Services.Add(t, item);
|
||||
SendServicePublishedEvent(t, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if specifed interface has been published, false if not
|
||||
/// </summary>
|
||||
/// <typeparam name="T">type of interface to check</typeparam>
|
||||
/// <returns>true if interface has been published; false if not published</returns>
|
||||
public static bool Exists<T>() where T : class
|
||||
{
|
||||
return Services.ContainsKey(typeof(T));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if specifed interface has been published, false if not
|
||||
/// </summary>
|
||||
/// <param name="t">type of interface to check</param>
|
||||
/// <returns>true if interface has been published; false if not published</returns>
|
||||
public static bool Exists(Type t)
|
||||
{
|
||||
return Services.ContainsKey(t);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns published service
|
||||
/// </summary>
|
||||
/// <typeparam name="T">interface type of service</typeparam>
|
||||
/// <returns>published service or exception if not currently published</returns>
|
||||
public static T Get<T>() where T : class
|
||||
{
|
||||
if (!Services.ContainsKey(typeof(T)))
|
||||
{
|
||||
throw new ArgumentException(string.Format("{0}: has not been published", typeof(T).Name));
|
||||
}
|
||||
|
||||
return Services[typeof(T)] as T;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears specified service
|
||||
/// </summary>
|
||||
/// <typeparam name="T">interface type of service to clear</typeparam>
|
||||
public static void Clear<T>() where T : class
|
||||
{
|
||||
if (Services.ContainsKey(typeof(T)))
|
||||
{
|
||||
SendServicePublishedEvent(typeof(T), false);
|
||||
Services.Remove(typeof(T));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears list of published interfaces
|
||||
/// </summary>
|
||||
/// <param name="interfaceList">list of interfaces to unpublish</param>
|
||||
public static void Clear(IEnumerable<Type> interfaceList)
|
||||
{
|
||||
foreach (var t in interfaceList)
|
||||
{
|
||||
if (!Services.ContainsKey(t)) continue;
|
||||
|
||||
SendServicePublishedEvent(t, false);
|
||||
Services.Remove(t);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sends a IServicePublishedEvent through the Event Manger to let subscribers know when
|
||||
/// a service is published or unpublished
|
||||
/// </summary>
|
||||
/// <param name="type">type of interface</param>
|
||||
/// <param name="published">true if being published, false if being unpublished</param>
|
||||
private static void SendServicePublishedEvent(Type type, bool published)
|
||||
{
|
||||
EventManager.EventManager.Publish<IServicePublishedEvent>(new ServicePublishedEvent
|
||||
{
|
||||
IsPublished = published,
|
||||
ServiceType = type
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
32
DataPRO/DataPRO.Core/ServiceManager/ServicePublishedEvent.cs
Normal file
32
DataPRO/DataPRO.Core/ServiceManager/ServicePublishedEvent.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace DataPro.Core.ServiceManager
|
||||
{
|
||||
/// <summary>
|
||||
/// Event fired when a service interface is published\unpublished
|
||||
/// </summary>
|
||||
public class ServicePublishedEvent : IServicePublishedEvent
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns type of service being published\unpublished
|
||||
/// </summary>
|
||||
public Type ServiceType
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if Service is being published, false if being unpublished
|
||||
/// </summary>
|
||||
public bool IsPublished
|
||||
{
|
||||
get;
|
||||
internal set;
|
||||
}
|
||||
}
|
||||
}
|
||||
84
DataPRO/DataPRO.Core/Settings/SettingsChangedEventArgs.cs
Normal file
84
DataPRO/DataPRO.Core/Settings/SettingsChangedEventArgs.cs
Normal file
@@ -0,0 +1,84 @@
|
||||
using System;
|
||||
|
||||
namespace DataPro.Core.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// Event arguments describing change to settings collection
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">key type used in collection</typeparam>
|
||||
/// <typeparam name="TItem">value type used in collection</typeparam>
|
||||
public class SettingsChangedEventArgs<TKey, TItem> : EventArgs
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="changeType">type of scenario change</param>
|
||||
public SettingsChangedEventArgs(ChangeSettingType changeType)
|
||||
{
|
||||
ChangeType = changeType;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="changeType">change type</param>
|
||||
/// <param name="key">key type used in collection</param>
|
||||
public SettingsChangedEventArgs(ChangeSettingType changeType, TKey key)
|
||||
{
|
||||
ChangeType = changeType;
|
||||
Key = key;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="changeType">change type</param>
|
||||
/// <param name="key">key type used in collection</param>
|
||||
/// <param name="item">value type used in collection</param>
|
||||
public SettingsChangedEventArgs(ChangeSettingType changeType, TKey key, TItem item)
|
||||
{
|
||||
ChangeType = changeType;
|
||||
Key = key;
|
||||
Item = item;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns type of scenario change
|
||||
/// </summary>
|
||||
public ChangeSettingType ChangeType
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// key associated with changed setting
|
||||
/// </summary>
|
||||
public TKey Key
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Value associated with changed settting
|
||||
/// </summary>
|
||||
public TItem Item
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Type of settings changed
|
||||
/// </summary>
|
||||
public enum ChangeSettingType
|
||||
{
|
||||
Add = 0,
|
||||
Remove = 1,
|
||||
Modified = 3,
|
||||
ClearAll = 4
|
||||
}
|
||||
|
||||
}
|
||||
241
DataPRO/DataPRO.Core/Settings/SettingsCollection.cs
Normal file
241
DataPRO/DataPRO.Core/Settings/SettingsCollection.cs
Normal file
@@ -0,0 +1,241 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
namespace DataPro.Core.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// Implements a dictionary with events when an item is changed
|
||||
/// </summary>
|
||||
/// <typeparam name="TKey">key type</typeparam>
|
||||
/// <typeparam name="TItem">value type</typeparam>
|
||||
/// <history>
|
||||
/// <list type="number">
|
||||
/// <item>{01/22/2014}. {RCD}. {Initial Version}</item>
|
||||
/// </list>
|
||||
/// </history>
|
||||
public class SettingsCollection<TKey, TItem> : IDictionary<TKey, TItem>
|
||||
{
|
||||
/// <summary>
|
||||
/// Event fired when an item changes in dictionary
|
||||
/// </summary>
|
||||
public event EventHandler<SettingsChangedEventArgs<TKey, TItem>> CollectionItemPropertyChanged;
|
||||
|
||||
/// <summary>
|
||||
/// List of stored items
|
||||
/// </summary>
|
||||
private readonly Dictionary<TKey, TItem> _items = new Dictionary<TKey, TItem>();
|
||||
|
||||
|
||||
#region IDictionary
|
||||
|
||||
/// <summary>
|
||||
/// Add item
|
||||
/// </summary>
|
||||
/// <param name="key">key</param>
|
||||
/// <param name="value">value</param>
|
||||
public void Add(TKey key, TItem value)
|
||||
{
|
||||
_items.Add(key, value);
|
||||
FireItemChangedEvent(ChangeSettingType.Add, key, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if item contains key
|
||||
/// </summary>
|
||||
/// <param name="key">key</param>
|
||||
/// <returns>true if key exists</returns>
|
||||
public bool ContainsKey(TKey key)
|
||||
{
|
||||
return _items.ContainsKey(key);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns all keys in collection
|
||||
/// </summary>
|
||||
public ICollection<TKey> Keys
|
||||
{
|
||||
get { return _items.Keys; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes key
|
||||
/// </summary>
|
||||
/// <param name="key">key</param>
|
||||
/// <returns>true if key removed</returns>
|
||||
public bool Remove(TKey key)
|
||||
{
|
||||
var res = _items.Remove(key);
|
||||
if (res) FireItemChangedEvent(ChangeSettingType.Remove, key);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Trys to get specified value
|
||||
/// </summary>
|
||||
/// <param name="key">key</param>
|
||||
/// <param name="value">value if key exists</param>
|
||||
/// <returns>true if key exists; false if it doesn't exist</returns>
|
||||
public bool TryGetValue(TKey key, out TItem value)
|
||||
{
|
||||
return _items.TryGetValue(key, out value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// List of values in collection
|
||||
/// </summary>
|
||||
public ICollection<TItem> Values
|
||||
{
|
||||
get { return _items.Values; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets/sets item in collection (overloads [] operator)
|
||||
/// </summary>
|
||||
/// <param name="key">key</param>
|
||||
/// <returns>item in collection</returns>
|
||||
public TItem this[TKey key]
|
||||
{
|
||||
get
|
||||
{
|
||||
return _items[key];
|
||||
}
|
||||
set
|
||||
{
|
||||
_items[key] = value;
|
||||
FireItemChangedEvent(ChangeSettingType.Add, key, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds new item
|
||||
/// </summary>
|
||||
/// <param name="item">new item to add</param>
|
||||
public void Add(KeyValuePair<TKey, TItem> item)
|
||||
{
|
||||
_items.Add(item.Key, item.Value);
|
||||
FireItemChangedEvent(ChangeSettingType.Add, item.Key, item.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears entire collection
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
_items.Clear();
|
||||
FireItemChangedEvent(ChangeSettingType.ClearAll);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if item is in collection
|
||||
/// </summary>
|
||||
/// <param name="item">item to check</param>
|
||||
/// <returns>true if item exists</returns>
|
||||
public bool Contains(KeyValuePair<TKey, TItem> item)
|
||||
{
|
||||
return _items.ContainsKey(item.Key) && _items.ContainsValue(item.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copys items to array
|
||||
/// </summary>
|
||||
/// <param name="array"></param>
|
||||
/// <param name="arrayIndex"></param>
|
||||
public void CopyTo(KeyValuePair<TKey, TItem>[] array, int arrayIndex)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns count of items
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get { return _items.Count; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if readonly collection
|
||||
/// </summary>
|
||||
public bool IsReadOnly
|
||||
{
|
||||
get { return false; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes specified item
|
||||
/// </summary>
|
||||
/// <param name="item">item to remove</param>
|
||||
/// <returns>true if item removed</returns>
|
||||
public bool Remove(KeyValuePair<TKey, TItem> item)
|
||||
{
|
||||
var res = _items.Remove(item.Key);
|
||||
if (res) FireItemChangedEvent(ChangeSettingType.Remove, item.Key);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return enumerator for collection
|
||||
/// </summary>
|
||||
/// <returns>enumerator</returns>
|
||||
public IEnumerator<KeyValuePair<TKey, TItem>> GetEnumerator()
|
||||
{
|
||||
return _items.GetEnumerator();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Return enumerator for collection
|
||||
/// </summary>
|
||||
/// <returns>enumerator</returns>
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return _items.GetEnumerator();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Private methods
|
||||
|
||||
/// <summary>
|
||||
/// Fires collection change event
|
||||
/// </summary>
|
||||
/// <param name="changeType">type of change</param>
|
||||
private void FireItemChangedEvent(ChangeSettingType changeType)
|
||||
{
|
||||
if (CollectionItemPropertyChanged != null)
|
||||
{
|
||||
CollectionItemPropertyChanged(this, new SettingsChangedEventArgs<TKey, TItem>(changeType));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires collection change event
|
||||
/// </summary>
|
||||
/// <param name="changeType">type of change</param>
|
||||
/// <param name="key">key</param>
|
||||
private void FireItemChangedEvent(ChangeSettingType changeType, TKey key)
|
||||
{
|
||||
if (CollectionItemPropertyChanged != null)
|
||||
{
|
||||
CollectionItemPropertyChanged(this, new SettingsChangedEventArgs<TKey, TItem>(changeType, key));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fires collection change event
|
||||
/// </summary>
|
||||
/// <param name="changeType">type of change</param>
|
||||
/// <param name="key">key</param>
|
||||
/// <param name="item">item</param>
|
||||
private void FireItemChangedEvent(ChangeSettingType changeType, TKey key, TItem item)
|
||||
{
|
||||
if (CollectionItemPropertyChanged != null)
|
||||
{
|
||||
CollectionItemPropertyChanged(this, new SettingsChangedEventArgs<TKey, TItem>(changeType, key, item));
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user