This commit is contained in:
2026-04-17 14:55:32 -04:00
commit bc3ac1d4c9
18017 changed files with 4371742 additions and 0 deletions

View File

@@ -0,0 +1 @@
12

View File

@@ -0,0 +1 @@
12

View File

@@ -0,0 +1,134 @@
using System;
using System.ComponentModel.Composition;
using System.Windows.Media.Imaging;
using DTS.Common.CPU;
using DTS.Common.Interface;
using Microsoft.Practices.Prism.Modularity;
using Microsoft.Practices.Unity;
[assembly: CPUName()]
[assembly: CUPImage()]
namespace DTS.Common.CPU
{
[Export(typeof(IModule))]
[Module(ModuleName = "CPU")]
public class CPUModule : IModule
{
/// <summary>
/// Injected unity container
/// </summary>
private readonly IUnityContainer _unityContainer;
/// <summary>
/// Initializes a new instance of the <see cref="CPUModule"/> class.
/// </summary>
/// <param name="unityContainer">Obtained reference of the unity container by using dependency injection.</param>
public CPUModule(IUnityContainer unityContainer)
{
_unityContainer = unityContainer;
}
public void Initialize()
{
// Register View & View-Model with Unity dependency injection container as a singleton.
_unityContainer.RegisterType<ICPUEngine, CPUEngine>();
//_unityContainer.RegisterType<IPropertyViewModel, PropertyViewModel>();
}
}
/// <summary>
/// Attribute class contains assembly name
/// </summary>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
public class CPUNameAttribute : TextAttribute
{
private readonly string _assemblyName;
public CPUNameAttribute() : this(null) { }
public CPUNameAttribute(string s)
{
_assemblyName = "CPUAsssembly";
}
public override string AssemblyName
{
get { return _assemblyName; }
}
public override Type GetAttributeType()
{
return typeof(TextAttribute);
}
public override string GetAssemblyName()
{
return AssemblyName;
}
}
/// <summary>
/// Attribute class contains assembly image and name - used on the Main screen to display available components
/// </summary>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
public class CUPImageAttribute : ImageAttribute
{
private BitmapImage _img;
public CUPImageAttribute() : this(null) { }
public override BitmapImage AssemblyImage
{
get { _img = AssemblyInfo.GetImage(AssemblyNames.CPU.ToString()); return _img; }
}
public CUPImageAttribute(string s)
{
_img = AssemblyInfo.GetImage(AssemblyNames.CPU.ToString());
}
public override Type GetAttributeType()
{
return typeof(ImageAttribute);
}
public override BitmapImage GetAssemblyImage()
{
return AssemblyImage;
}
public override string GetAssemblyName()
{
return AssemblyName;
}
public override eAssemblyRegion GetAssemblyRegion()
{
return AssemblyRegion;
}
public override string GetAssemblyGroup()
{
return AssemblyGroup;
}
private string _name;
public override string AssemblyName
{
get { _name = AssemblyNames.CPU.ToString(); return _name; }
}
private string _group;
public override string AssemblyGroup
{
get { _group = eAssemblyGroups.Viewer.ToString(); return _group; }
}
private eAssemblyRegion _region;
public override eAssemblyRegion AssemblyRegion
{
get { _region = eAssemblyRegion.NotAssigned; return _region; }
}
}
}

View File

@@ -0,0 +1,72 @@
using System.ComponentModel;
using Microsoft.Practices.Prism.Events;
using Microsoft.Practices.Prism.Interactivity.InteractionRequest;
using Microsoft.Practices.Prism.Regions;
using Microsoft.Practices.Unity;
using Microsoft.Practices.ServiceLocation;
using DTS.Common.Events;
using DTS.Common.Interface;
using DTS.Common.Base;
using System;
namespace DTS.Common.CPU
{
public class CPUEngine : ICPUEngine
{
private IEventAggregator _eventAggregator { get; set; }
private new IRegionManager _regionManager;
private IUnityContainer _unityContainer { get; set; }
public IServiceLocator _serviceLocator { get; private set; }
public InteractionRequest<Notification> NotificationRequest { get; private set; }
public new InteractionRequest<Confirmation> ConfirmationRequest { get; private set; }
public CPUEngine()
{
_unityContainer= ServiceLocator.Current.GetInstance<IUnityContainer>();
_eventAggregator = _unityContainer.Resolve<IEventAggregator>();
_serviceLocator = _unityContainer.Resolve<IServiceLocator>();
NotificationRequest = new InteractionRequest<Notification>();
ConfirmationRequest = new InteractionRequest<Confirmation>();
_eventAggregator.GetEvent<RaiseNotification>().Subscribe(OnRaiseNotification);
_eventAggregator.GetEvent<ShowStatus>().Subscribe(OnStatusChange);
}
/// <summary>
/// Private Event handler for Status change event.
/// </summary>
private void OnStatusChange(StatusInfo content)
{
//IsBusy = content.IsBusy;
//IsBusyMessage = content.Text;
//NotificationRequest.Raise(new Notification { Content = content, Title = "DataPRO" });
}
/// <summary>
/// Private Event handler for RaiseNotification event.
/// </summary>
private void OnRaiseNotification(NotificationContentEventArgs eventArgsWithTitle)
{
// Notification object expects a NotificationContentEventArgsWithoutTitle object and a Title string.
var eventArgsWithoutTitle = new NotificationContentEventArgs(eventArgsWithTitle.Message, eventArgsWithTitle.MessageDetails, eventArgsWithTitle.Image);
NotificationRequest.Raise(new Notification
{
Content = eventArgsWithoutTitle,
Title = eventArgsWithTitle.Title
});
}
public new event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
var eventHandler = PropertyChanged;
if (eventHandler != null) { eventHandler(this, new PropertyChangedEventArgs(propertyName)); }
}
}
}

View File

@@ -0,0 +1,7 @@
namespace DTS.Common.CPU
{
public class BREngine
{
}
}

View File

@@ -0,0 +1,96 @@
<?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>{761A8290-184D-4610-967C-25B08D27A1A9}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DTS.Common.CPU</RootNamespace>
<AssemblyName>DTS.Common.CPU</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SccProjectName>
</SccProjectName>
<SccLocalPath>
</SccLocalPath>
<SccAuxPath>
</SccAuxPath>
<SccProvider>
</SccProvider>
<TargetFrameworkProfile />
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Expression.Interactions, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Expression.Interactions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.Prism">
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Practices.Prism.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.Prism.Interactivity">
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Practices.Prism.Interactivity.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.Prism.UnityExtensions">
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Practices.Prism.UnityExtensions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.ServiceLocation">
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Practices.ServiceLocation.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.Unity, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Practices.Unity.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.Unity.Interception">
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Practices.Unity.Interception.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\DTS.Common\lib\System.Windows.Interactivity.dll</HintPath>
</Reference>
<Reference Include="System.Xaml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="Classes\BREngine.cs" />
<Compile Include="Classes\CPUEngine.cs" />
<Compile Include="CPUModule.cs" />
<Compile Include="Properties\Annotations.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DTS.Common.Core\DTS.Common.Core.csproj">
<Project>{fab1f470-1574-4301-b56e-d3364aa93679}</Project>
<Name>DTS.Common.Core</Name>
</ProjectReference>
<ProjectReference Include="..\DTS.Common\DTS.Common.csproj">
<Project>{114edc77-f3b5-4576-a91b-40818d503b55}</Project>
<Name>DTS.Common</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>copy "$(TargetPath)" "$(SolutionDir)..\RunTimeModules\$(TargetFileName)"</PostBuildEvent>
</PropertyGroup>
<!-- 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>

View 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("DTS.Common.CPU")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DTS.Common.CPU")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[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("a68ef337-debf-4265-8dec-8acf01e76ee6")]
// 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")]

Binary file not shown.

View File

View File

@@ -0,0 +1,134 @@
using System;
using System.ComponentModel.Composition;
using System.Windows.Media.Imaging;
using DTS.Common.CPU;
using DTS.Common.Interface;
using Microsoft.Practices.Prism.Modularity;
using Microsoft.Practices.Unity;
[assembly: CPUName()]
[assembly: CUPImage()]
namespace DTS.Common.CPU
{
[Export(typeof(IModule))]
[Module(ModuleName = "CPU")]
public class CPUModule : IModule
{
/// <summary>
/// Injected unity container
/// </summary>
private readonly IUnityContainer _unityContainer;
/// <summary>
/// Initializes a new instance of the <see cref="CPUModule"/> class.
/// </summary>
/// <param name="unityContainer">Obtained reference of the unity container by using dependency injection.</param>
public CPUModule(IUnityContainer unityContainer)
{
_unityContainer = unityContainer;
}
public void Initialize()
{
// Register View & View-Model with Unity dependency injection container as a singleton.
_unityContainer.RegisterType<ICPUEngine, CPUEngine>();
//_unityContainer.RegisterType<IPropertyViewModel, PropertyViewModel>();
}
}
/// <summary>
/// Attribute class contains assembly name
/// </summary>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
public class CPUNameAttribute : TextAttribute
{
private readonly string _assemblyName;
public CPUNameAttribute() : this(null) { }
public CPUNameAttribute(string s)
{
_assemblyName = "CPUAsssembly";
}
public override string AssemblyName
{
get { return _assemblyName; }
}
public override Type GetAttributeType()
{
return typeof(TextAttribute);
}
public override string GetAssemblyName()
{
return AssemblyName;
}
}
/// <summary>
/// Attribute class contains assembly image and name - used on the Main screen to display available components
/// </summary>
[AttributeUsage(AttributeTargets.Assembly, AllowMultiple = false)]
public class CUPImageAttribute : ImageAttribute
{
private BitmapImage _img;
public CUPImageAttribute() : this(null) { }
public override BitmapImage AssemblyImage
{
get { _img = AssemblyInfo.GetImage(AssemblyNames.CPU.ToString()); return _img; }
}
public CUPImageAttribute(string s)
{
_img = AssemblyInfo.GetImage(AssemblyNames.CPU.ToString());
}
public override Type GetAttributeType()
{
return typeof(ImageAttribute);
}
public override BitmapImage GetAssemblyImage()
{
return AssemblyImage;
}
public override string GetAssemblyName()
{
return AssemblyName;
}
public override eAssemblyRegion GetAssemblyRegion()
{
return AssemblyRegion;
}
public override string GetAssemblyGroup()
{
return AssemblyGroup;
}
private string _name;
public override string AssemblyName
{
get { _name = AssemblyNames.CPU.ToString(); return _name; }
}
private string _group;
public override string AssemblyGroup
{
get { _group = eAssemblyGroups.Viewer.ToString(); return _group; }
}
private eAssemblyRegion _region;
public override eAssemblyRegion AssemblyRegion
{
get { _region = eAssemblyRegion.NotAssigned; return _region; }
}
}
}

View File

@@ -0,0 +1,7 @@
namespace DTS.Common.CPU
{
public class BREngine
{
}
}

View File

@@ -0,0 +1,72 @@
using System.ComponentModel;
using Microsoft.Practices.Prism.Events;
using Microsoft.Practices.Prism.Interactivity.InteractionRequest;
using Microsoft.Practices.Prism.Regions;
using Microsoft.Practices.Unity;
using Microsoft.Practices.ServiceLocation;
using DTS.Common.Events;
using DTS.Common.Interface;
using DTS.Common.Base;
using System;
namespace DTS.Common.CPU
{
public class CPUEngine : ICPUEngine
{
private IEventAggregator _eventAggregator { get; set; }
private new IRegionManager _regionManager;
private IUnityContainer _unityContainer { get; set; }
public IServiceLocator _serviceLocator { get; private set; }
public InteractionRequest<Notification> NotificationRequest { get; private set; }
public new InteractionRequest<Confirmation> ConfirmationRequest { get; private set; }
public CPUEngine()
{
_unityContainer= ServiceLocator.Current.GetInstance<IUnityContainer>();
_eventAggregator = _unityContainer.Resolve<IEventAggregator>();
_serviceLocator = _unityContainer.Resolve<IServiceLocator>();
NotificationRequest = new InteractionRequest<Notification>();
ConfirmationRequest = new InteractionRequest<Confirmation>();
_eventAggregator.GetEvent<RaiseNotification>().Subscribe(OnRaiseNotification);
_eventAggregator.GetEvent<ShowStatus>().Subscribe(OnStatusChange);
}
/// <summary>
/// Private Event handler for Status change event.
/// </summary>
private void OnStatusChange(StatusInfo content)
{
//IsBusy = content.IsBusy;
//IsBusyMessage = content.Text;
//NotificationRequest.Raise(new Notification { Content = content, Title = "DataPRO" });
}
/// <summary>
/// Private Event handler for RaiseNotification event.
/// </summary>
private void OnRaiseNotification(NotificationContentEventArgs eventArgsWithTitle)
{
// Notification object expects a NotificationContentEventArgsWithoutTitle object and a Title string.
var eventArgsWithoutTitle = new NotificationContentEventArgs(eventArgsWithTitle.Message, eventArgsWithTitle.MessageDetails, eventArgsWithTitle.Image);
NotificationRequest.Raise(new Notification
{
Content = eventArgsWithoutTitle,
Title = eventArgsWithTitle.Title
});
}
public new event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyChanged(string propertyName)
{
var eventHandler = PropertyChanged;
if (eventHandler != null) { eventHandler(this, new PropertyChangedEventArgs(propertyName)); }
}
}
}

View File

@@ -0,0 +1,96 @@
<?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>{761A8290-184D-4610-967C-25B08D27A1A9}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DTS.Common.CPU</RootNamespace>
<AssemblyName>DTS.Common.CPU</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SccProjectName>
</SccProjectName>
<SccLocalPath>
</SccLocalPath>
<SccAuxPath>
</SccAuxPath>
<SccProvider>
</SccProvider>
<TargetFrameworkProfile />
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.Expression.Interactions, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Expression.Interactions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.Prism">
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Practices.Prism.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.Prism.Interactivity">
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Practices.Prism.Interactivity.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.Prism.UnityExtensions">
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Practices.Prism.UnityExtensions.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.ServiceLocation">
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Practices.ServiceLocation.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.Unity, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Practices.Unity.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Practices.Unity.Interception">
<HintPath>..\DTS.Common\lib\PrismLibrary\Microsoft.Practices.Unity.Interception.dll</HintPath>
</Reference>
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
<Reference Include="System" />
<Reference Include="System.ComponentModel.Composition" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.Windows" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Windows.Interactivity, Version=4.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\DTS.Common\lib\System.Windows.Interactivity.dll</HintPath>
</Reference>
<Reference Include="System.Xaml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="WindowsBase" />
</ItemGroup>
<ItemGroup>
<Compile Include="Classes\BREngine.cs" />
<Compile Include="Classes\CPUEngine.cs" />
<Compile Include="CPUModule.cs" />
<Compile Include="Properties\Annotations.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DTS.Common.Core\DTS.Common.Core.csproj">
<Project>{fab1f470-1574-4301-b56e-d3364aa93679}</Project>
<Name>DTS.Common.Core</Name>
</ProjectReference>
<ProjectReference Include="..\DTS.Common\DTS.Common.csproj">
<Project>{114edc77-f3b5-4576-a91b-40818d503b55}</Project>
<Name>DTS.Common</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>copy "$(TargetPath)" "$(SolutionDir)..\RunTimeModules\$(TargetFileName)"</PostBuildEvent>
</PropertyGroup>
<!-- 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>

File diff suppressed because it is too large Load Diff

View 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("DTS.Common.CPU")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DTS.Common.CPU")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[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("a68ef337-debf-4265-8dec-8acf01e76ee6")]
// 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")]

View File

@@ -0,0 +1 @@
12

View File

@@ -0,0 +1 @@
12

View File

@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DTS.Common.Calculations
{
/// <summary>
/// Filtered Channel Data
/// simple class for holding generic data for calculations
/// in the future I'd like to be able to accept channels with different units and convert them
/// to a common unit, so I add support for that now
/// </summary>
public class ChannelData
{
/// <summary>
/// Engineering units of Data
/// </summary>
public string Units { get; }
/// <summary>
/// Pre-Filtered EU data
/// </summary>
public double[] FilteredEU { get; set; }
/// <summary>
/// Constructs a ChannelData object
/// </summary>
/// <param name="units">Engineering units of data</param>
public ChannelData(string units)
{
Units = units;
}
}
}

View File

@@ -0,0 +1,69 @@
using System;
namespace DTS.Common.Calculations
{
public class HeadInjuryCriterion
{
/// <summary>
/// Calculates the head injury criterion given a resultant channel, and a desired clip length
/// </summary>
/// <param name="resultant">Acceleration vector (x,y,z resultant)</param>
/// <param name="SPS">Actual sample rate</param>
/// <param name="clipLengthMS">Length in ms </param>
/// <returns>MAX Head Injury Criterion over the data input for the clip requested</returns>
public static HICResult GetHeadInjuryCriterion(ChannelData resultant, double SPS, int clipLengthMS)
{
System.Diagnostics.Trace.Assert(SPS > 0, "Actual sample rate must be positive");
System.Diagnostics.Trace.Assert(clipLengthMS > 0, "Clip length must be positive");
int maxHICPoint = int.MinValue;
double maxHIC = int.MinValue;
int maxHICEndPoint = int.MinValue;
int maxclip = Convert.ToInt32(Math.Ceiling(clipLengthMS * SPS / 1000D));
for (int clip = 1; clip <= maxclip; clip++)
{
System.Diagnostics.Trace.Assert(clip < resultant.FilteredEU.Length, string.Format("data must be atleast {0} ms", clipLengthMS));
double clipInSeconds = clip / SPS;
for (int i = 0; i < resultant.FilteredEU.Length - clip; i++)
{
//note we are exhaustively recalculating sums, we can do this much better without a doubt, but lets get the
//first method done (brute force)
//also note, definite integral doesn't include last point, so we have to add one point back in
double integral = Integral.DefiniteIntegral(resultant.FilteredEU, i, i + clip, SPS);
double hic = clipInSeconds * Math.Pow(integral / clipInSeconds, 2.5D);
if (hic > maxHIC) { maxHIC = hic; maxHICPoint = i; maxHICEndPoint = i + clip; }
}
}
return new HICResult(maxHIC, clipLengthMS, maxHICPoint, maxHICEndPoint);
}
/// <summary>
/// helper class for storing/handling hic results
/// </summary>
public class HICResult
{
public int StartSample { get; }
public int EndSample { get; }
public int HicLengthMS { get; }
public double HIC { get; }
/// <summary>
/// constructs a new HIC result
/// </summary>
/// <param name="hic">HIC value</param>
/// <param name="hicLength">length of HIC in ms</param>
/// <param name="endSample">start sample of HIC</param>
/// <param name="startSample">end sample of HIC</param>
public HICResult(double hic, int hicLength, int startSample, int endSample)
{
StartSample = startSample;
EndSample = endSample;
HicLengthMS = hicLength;
HIC = hic;
}
}
}
}

View File

@@ -0,0 +1,47 @@
using System.Collections.Generic;
using System.Linq;
namespace DTS.Common.Calculations
{
public static class Resultant
{
/// <summary>
/// generates a resultant channel given input vectors
/// Will throw an assertion if lengths of data don't match, or if
/// units don't match
/// </summary>
/// <param name="channels">List of channels to combine via
/// sum of squares
/// </param>
/// <returns>
/// resultant vector from sum of squares of inputs
/// </returns>
public static ChannelData GenerateResultantChannel(List<ChannelData> channels)
{
int length = (from ch in channels select ch.FilteredEU.Length).Max();
foreach (var ch in channels) { System.Diagnostics.Trace.Assert(ch.FilteredEU.Length == length); }
//make sure the channels are all the same units and lengths,
//we assert here since the higher level should be expected to provide clean inputs
var units = (from ch in channels select ch.Units).Distinct();
System.Diagnostics.Trace.Assert(units.Count() == 1);
var values = new List<double>();
//in a future version we can parallize this for efficiency
//values.Add will need to be replaced by an indexer when we do
for (int i = 0; i < length; i++)
{
double d = 0D;
foreach (var ch in channels)
{
d += ch.FilteredEU[i] * ch.FilteredEU[i];
}
values.Add(System.Math.Sqrt(d));
}
var cd = new ChannelData(units.First());
cd.FilteredEU = values.ToArray();
return cd;
}
}
}

View File

@@ -0,0 +1,28 @@
namespace DTS.Common.Calculations
{
public static class Integral
{
/// <summary>
/// integrates a channel over an interval
/// </summary>
/// <param name="input">data to integrate</param>
/// <param name="start">index to start integration at (inclusive)</param>
/// <param name="end">index to end integration at (inclusive)</param>
/// <returns></returns>
public static double DefiniteIntegral(double[] input, int start, int end, double SPS)
{
//we use trapezoidal summation to get integral, there is an assumption that the input data is
//tightly time aligned (otherwise we'd have to divide each interval by the actual distance, and not 1/2)
//=(SUMPRODUCT(H25:H56,A26:A57)-SUMPRODUCT(A25:A56,H26:H57)+A57*H57-A25*H25)/2
double d = 0;
for (int i = start + 1; i < end; i++)
{
d += 2D * input[i];
}
d += input[start];
d += input[end];
return .5D * d / SPS;
}
}
}

View File

@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{5CE6F27B-1C5B-4101-88DE-58A30B1E5F37}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DTS.Common.Calculations</RootNamespace>
<AssemblyName>Calculations</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>3.5</OldToolsVersion>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ChannelData.cs" />
<Compile Include="HeadInjuryCriterion.cs" />
<Compile Include="Integral.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Resultant.cs" />
</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>

View 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("HeadInjuryCriterion")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HeadInjuryCriterion")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[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("a83e3800-290f-4513-9756-d37168152099")]
// 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")]

Binary file not shown.

View File

@@ -0,0 +1,35 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DTS.Common.Calculations
{
/// <summary>
/// Filtered Channel Data
/// simple class for holding generic data for calculations
/// in the future I'd like to be able to accept channels with different units and convert them
/// to a common unit, so I add support for that now
/// </summary>
public class ChannelData
{
/// <summary>
/// Engineering units of Data
/// </summary>
public string Units { get; }
/// <summary>
/// Pre-Filtered EU data
/// </summary>
public double[] FilteredEU { get; set; }
/// <summary>
/// Constructs a ChannelData object
/// </summary>
/// <param name="units">Engineering units of data</param>
public ChannelData(string units)
{
Units = units;
}
}
}

View File

@@ -0,0 +1,89 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>9.0.21022</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{5CE6F27B-1C5B-4101-88DE-58A30B1E5F37}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>DTS.Common.Calculations</RootNamespace>
<AssemblyName>Calculations</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<FileUpgradeFlags>
</FileUpgradeFlags>
<UpgradeBackupLocation>
</UpgradeBackupLocation>
<OldToolsVersion>3.5</OldToolsVersion>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|x86' ">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|x86' ">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Xml.Linq">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data.DataSetExtensions">
<RequiredTargetFramework>3.5</RequiredTargetFramework>
</Reference>
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ChannelData.cs" />
<Compile Include="HeadInjuryCriterion.cs" />
<Compile Include="Integral.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Resultant.cs" />
</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>

View File

@@ -0,0 +1,69 @@
using System;
namespace DTS.Common.Calculations
{
public class HeadInjuryCriterion
{
/// <summary>
/// Calculates the head injury criterion given a resultant channel, and a desired clip length
/// </summary>
/// <param name="resultant">Acceleration vector (x,y,z resultant)</param>
/// <param name="SPS">Actual sample rate</param>
/// <param name="clipLengthMS">Length in ms </param>
/// <returns>MAX Head Injury Criterion over the data input for the clip requested</returns>
public static HICResult GetHeadInjuryCriterion(ChannelData resultant, double SPS, int clipLengthMS)
{
System.Diagnostics.Trace.Assert(SPS > 0, "Actual sample rate must be positive");
System.Diagnostics.Trace.Assert(clipLengthMS > 0, "Clip length must be positive");
int maxHICPoint = int.MinValue;
double maxHIC = int.MinValue;
int maxHICEndPoint = int.MinValue;
int maxclip = Convert.ToInt32(Math.Ceiling(clipLengthMS * SPS / 1000D));
for (int clip = 1; clip <= maxclip; clip++)
{
System.Diagnostics.Trace.Assert(clip < resultant.FilteredEU.Length, string.Format("data must be atleast {0} ms", clipLengthMS));
double clipInSeconds = clip / SPS;
for (int i = 0; i < resultant.FilteredEU.Length - clip; i++)
{
//note we are exhaustively recalculating sums, we can do this much better without a doubt, but lets get the
//first method done (brute force)
//also note, definite integral doesn't include last point, so we have to add one point back in
double integral = Integral.DefiniteIntegral(resultant.FilteredEU, i, i + clip, SPS);
double hic = clipInSeconds * Math.Pow(integral / clipInSeconds, 2.5D);
if (hic > maxHIC) { maxHIC = hic; maxHICPoint = i; maxHICEndPoint = i + clip; }
}
}
return new HICResult(maxHIC, clipLengthMS, maxHICPoint, maxHICEndPoint);
}
/// <summary>
/// helper class for storing/handling hic results
/// </summary>
public class HICResult
{
public int StartSample { get; }
public int EndSample { get; }
public int HicLengthMS { get; }
public double HIC { get; }
/// <summary>
/// constructs a new HIC result
/// </summary>
/// <param name="hic">HIC value</param>
/// <param name="hicLength">length of HIC in ms</param>
/// <param name="endSample">start sample of HIC</param>
/// <param name="startSample">end sample of HIC</param>
public HICResult(double hic, int hicLength, int startSample, int endSample)
{
StartSample = startSample;
EndSample = endSample;
HicLengthMS = hicLength;
HIC = hic;
}
}
}
}

View File

@@ -0,0 +1,28 @@
namespace DTS.Common.Calculations
{
public static class Integral
{
/// <summary>
/// integrates a channel over an interval
/// </summary>
/// <param name="input">data to integrate</param>
/// <param name="start">index to start integration at (inclusive)</param>
/// <param name="end">index to end integration at (inclusive)</param>
/// <returns></returns>
public static double DefiniteIntegral(double[] input, int start, int end, double SPS)
{
//we use trapezoidal summation to get integral, there is an assumption that the input data is
//tightly time aligned (otherwise we'd have to divide each interval by the actual distance, and not 1/2)
//=(SUMPRODUCT(H25:H56,A26:A57)-SUMPRODUCT(A25:A56,H26:H57)+A57*H57-A25*H25)/2
double d = 0;
for (int i = start + 1; i < end; i++)
{
d += 2D * input[i];
}
d += input[start];
d += input[end];
return .5D * d / SPS;
}
}
}

View 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("HeadInjuryCriterion")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("HeadInjuryCriterion")]
[assembly: AssemblyCopyright("Copyright © 2013")]
[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("a83e3800-290f-4513-9756-d37168152099")]
// 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")]

View File

@@ -0,0 +1,47 @@
using System.Collections.Generic;
using System.Linq;
namespace DTS.Common.Calculations
{
public static class Resultant
{
/// <summary>
/// generates a resultant channel given input vectors
/// Will throw an assertion if lengths of data don't match, or if
/// units don't match
/// </summary>
/// <param name="channels">List of channels to combine via
/// sum of squares
/// </param>
/// <returns>
/// resultant vector from sum of squares of inputs
/// </returns>
public static ChannelData GenerateResultantChannel(List<ChannelData> channels)
{
int length = (from ch in channels select ch.FilteredEU.Length).Max();
foreach (var ch in channels) { System.Diagnostics.Trace.Assert(ch.FilteredEU.Length == length); }
//make sure the channels are all the same units and lengths,
//we assert here since the higher level should be expected to provide clean inputs
var units = (from ch in channels select ch.Units).Distinct();
System.Diagnostics.Trace.Assert(units.Count() == 1);
var values = new List<double>();
//in a future version we can parallize this for efficiency
//values.Add will need to be replaced by an indexer when we do
for (int i = 0; i < length; i++)
{
double d = 0D;
foreach (var ch in channels)
{
d += ch.FilteredEU[i] * ch.FilteredEU[i];
}
values.Add(System.Math.Sqrt(d));
}
var cd = new ChannelData(units.First());
cd.FilteredEU = values.ToArray();
return cd;
}
}
}

View File

@@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = "")]

View File

@@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]

View File

@@ -0,0 +1 @@
12

View File

@@ -0,0 +1 @@
12

View File

@@ -0,0 +1,139 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1">
<Class Name="DTS.Common.Core.Config.DTSConfig" Collapsed="true">
<Position X="0.5" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AIAQAAAEAACAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAIA=</HashCode>
<FileName>Config\DTSConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.Core.DTSConstants" Collapsed="true">
<Position X="2.25" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAgAAAAA=</HashCode>
<FileName>DTSConstants.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.Core.EventManager.EventManager" Collapsed="true">
<Position X="4" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAIIAAACAAGAEAACAAAAAACAAAAQAAAAABAAAA=</HashCode>
<FileName>EventManager\EventManager.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.Core.EventManager.EventMetaData&lt;T&gt;" Collapsed="true">
<Position X="5.75" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA=</HashCode>
<FileName>EventManager\EventManager.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.Core.PluginLib.PluginConfig" Collapsed="true">
<Position X="4" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAgAAAIAAAAAAAAAAAAAA=</HashCode>
<FileName>PluginLib\PluginConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.Core.PluginLib.PluginConfigData" Collapsed="true">
<Position X="5.75" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAA=</HashCode>
<FileName>PluginLib\PluginConfigData.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.Core.PluginLib.PluginConfigSectionHandler" Collapsed="true">
<Position X="0.5" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>PluginLib\PluginConfigSectionHandler.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.Core.PluginLib.FilterHashKeyCollection" Collapsed="true">
<Position X="2.25" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAACAAAAAAAAAAAACAAAAAAAAAABAAAAAAAAAAAAAAA=</HashCode>
<FileName>PluginLib\PluginConfigSectionHandler.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.Core.PluginLib.FilterHashElement" Collapsed="true">
<Position X="0.5" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAgAAAAAAA=</HashCode>
<FileName>PluginLib\PluginConfigSectionHandler.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.Core.PluginLib.PluginManager" Collapsed="true">
<Position X="2.25" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AEAABAAAAAAEAACAAAMAAAAAAAAAAAAAAgAAAAAAAAA=</HashCode>
<FileName>PluginLib\PluginManager.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.Core.ServiceManager.ServiceManager" Collapsed="true">
<Position X="4" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>gAAAAAAAAAAAAABAAEAAAAABAAAAAAAAAAAAAAFAAAA=</HashCode>
<FileName>ServiceManager\ServiceManager.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.Core.ServiceManager.ServicePublishedEvent" Collapsed="true" BaseTypeListCollapsed="true">
<Position X="5.75" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAA=</HashCode>
<FileName>ServiceManager\ServicePublishedEvent.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" Collapsed="true" />
</Class>
<Class Name="DTS.Common.Core.Settings.SettingsChangedEventArgs&lt;TKey, TItem&gt;" Collapsed="true">
<Position X="0.5" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAQAAAEAAAAEAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Settings\SettingsChangedEventArgs.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.Core.Settings.SettingsCollection&lt;TKey, TItem&gt;" Collapsed="true" BaseTypeListCollapsed="true">
<Position X="2.25" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>CAIAAAAAAAAEABAQCAAABAQAABAAAAAEAAAgAABwKAA=</HashCode>
<FileName>Settings\SettingsCollection.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" Collapsed="true" />
</Class>
<Interface Name="DTS.Common.Core.ServiceManager.IServicePublishedEvent" Collapsed="true">
<Position X="0.5" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAA=</HashCode>
<FileName>ServiceManager\IServicePublishedEvent.cs</FileName>
</TypeIdentifier>
</Interface>
<Enum Name="DTS.Common.Core.EventManager.EventDiagnosticType" Collapsed="true">
<Position X="2.25" Y="5.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAABAAAAAAAAAAAAAEIACAAAAAAABAAAA=</HashCode>
<FileName>EventManager\EventManager.cs</FileName>
</TypeIdentifier>
</Enum>
<Enum Name="DTS.Common.Core.Settings.ChangeSettingType" Collapsed="true">
<Position X="0.5" Y="5.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAIAAAAAAAAAAABAABAABAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Settings\SettingsChangedEventArgs.cs</FileName>
</TypeIdentifier>
</Enum>
<Delegate Name="DTS.Common.Core.EventManager.SubscriberCallbackDelegate&lt;T&gt;" Collapsed="true">
<Position X="2.25" Y="6.75" Width="1.5" />
<TypeIdentifier>
<HashCode>BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>EventManager\EventManager.cs</FileName>
</TypeIdentifier>
</Delegate>
<Delegate Name="DTS.Common.Core.EventManager.DiagnosticCallbackDelegate" Collapsed="true">
<Position X="0.5" Y="6.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAACAAEAAAAAAAAAEAAAABAAAAAAAAAAAAAA=</HashCode>
<FileName>EventManager\EventManager.cs</FileName>
</TypeIdentifier>
</Delegate>
<Font Name="Segoe UI" Size="9" />
</ClassDiagram>

View File

@@ -0,0 +1,46 @@
using System.Configuration;
namespace DTS.Common.Core.PluginLib
{
/// <summary>
/// Support class that parses data from DTS.Common.Core.PluginLib.Config configuration section
/// </summary>
public class PluginConfigSectionHandler : ConfigurationSection
{
[ConfigurationProperty("PluginFolders")]
public FilterHashKeyCollection HashKeys => (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] => (FilterHashElement)BaseGet(idx);
}
public class FilterHashElement : ConfigurationElement
{
[ConfigurationProperty("key", DefaultValue = "", IsKey = true, IsRequired = true)]
public string Key
{
get => (string)base["key"];
set => base["key"] = value;
}
[ConfigurationProperty("value", DefaultValue = "", IsKey = false, IsRequired = false)]
public string Value
{
get => (string)base["value"];
set => base["value"] = value;
}
}
}

View File

@@ -0,0 +1,100 @@
using DTS.Common.Utilities.Logging;
using System;
using System.Configuration;
using System.Linq;
// ReSharper disable InconsistentNaming
// ReSharper disable EmptyConstructor
namespace DTS.Common.Core.Config
{
public static class DTSConfig
{
private static string AltConfigPath;
public static string AltConfigPathGet()
{
lock (MyLock)
{
return AltConfigPath;
}
}
public static void AltConfigPathSet(string path)
{
lock (MyLock)
{
AltConfigPath = path;
}
}
// static constructor
static DTSConfig()
{
}
public static void DTSConfigInit(string path)
{
SetAltConfigPath(path);
}
private static object MyLock = new object();
/// <summary>
/// Static variable to hold alternate configuration file
/// </summary>
private static Configuration AltConfig;
public static Configuration GetAltConfig()
{
lock (MyLock)
{
return AltConfig;
}
}
/// <summary>
/// Static variable to hold alternate configuration file
/// </summary>
/// <history>
///
/// </history>
public static void SetAltConfigPath(string path)
{
lock (MyLock)
{
AltConfigPath = path;
var dtsConfig = new ExeConfigurationFileMap
{
ExeConfigFilename = string.IsNullOrEmpty(AltConfigPath) ? DTSConstants.CustomConfigPath : AltConfigPath
};
AltConfig = ConfigurationManager.OpenMappedExeConfiguration(dtsConfig, ConfigurationUserLevel.None, true);
}
}
/// <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 = AltConfig.AppSettings.Settings.Cast<KeyValueConfigurationElement>().FirstOrDefault(setting => setting.Key == key);
if (appSetting == null)
{
APILogger.Log(
$"## AltConfig.AppSettings.Settings.Cast<KeyValueConfigurationElement>().FirstOrDefault(setting => setting.Key == key) is null for 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)
{
var section = AltConfig.GetSection(sectionName);
if (section == null)
{
APILogger.Log($"## AltConfig.GetSection(sectionName) is null for sectionName={sectionName}");
}
return section;
}
}
}

View File

@@ -0,0 +1,84 @@
using System;
namespace DTS.Common.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
}
}

View File

@@ -0,0 +1,9 @@
// ReSharper disable InconsistentNaming
namespace DTS.Common.Core
{
public static class DTSConstants
{
public const string CustomConfigPath = @"C:\dev\DTS.Viewer\bin\Debug\DTS.Viewer.exe.config";
public const string ViewerConfigPath = @"C:\dev\DTS.Viewer\bin\Debug\DTS.Viewer.exe.config";
}
}

View File

@@ -0,0 +1,193 @@
using System;
using System.Collections.Generic;
using System.Reflection;
namespace DTS.Common.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?.Method);
}
}
/// <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 =>
{
return p is EventMetaData<T> eventMetaData && 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 = $"{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
}
internal class EventMetaData<T> where T : class
{
public Predicate<T> EventFilter { get; set; }
public SubscriberCallbackDelegate<T> Callback { get; set; }
}
}

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>

View File

@@ -0,0 +1,20 @@
using System;
namespace DTS.Common.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; }
}
}

View File

@@ -0,0 +1,14 @@
using System.Xml.Serialization;
namespace DTS.Common.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;
}
}

View File

@@ -0,0 +1,27 @@
using DTS.Common.Core.Config;
// ReSharper disable InconsistentNaming
namespace DTS.Common.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 DTSPlugins = "DTSPlugins";
/// <summary>
/// concatenate plugin name from app setting with class exporter name for DTS plugins
/// </summary>
/// <param name="setting"></param>
/// <returns></returns>
public static string GetDTSPluginsSetting(string setting)
{
return DTSConfig.GetAppSetting(DTSPlugins) + "." + setting;
}
}
}

View File

@@ -0,0 +1,28 @@
using System;
namespace DTS.Common.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;
}
}
}

View File

@@ -0,0 +1,141 @@
using System;
using System.Collections.Generic;
// ReSharper disable InconsistentNaming
namespace DTS.Common.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($"{typeof(T).Name}: has already been published");
}
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($"{t.Name}: has already been published");
}
}
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($"{typeof(T).Name}: has not been published");
}
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
});
}
}
}

View File

@@ -0,0 +1,213 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace DTS.Common.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>
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);
}
/// <inheritdoc />
/// <summary>
/// Returns all keys in collection
/// </summary>
public ICollection<TKey> Keys => _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 => _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 => _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 => _items.Count;
/// <summary>
/// Returns true if readonly collection
/// </summary>
public bool IsReadOnly => 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)
{
CollectionItemPropertyChanged?.Invoke(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)
{
CollectionItemPropertyChanged?.Invoke(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)
{
CollectionItemPropertyChanged?.Invoke(this, new SettingsChangedEventArgs<TKey, TItem>(changeType, key, item));
}
#endregion
}
}

View File

@@ -0,0 +1,108 @@
<?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>DTS.Common.Core</RootNamespace>
<AssemblyName>DTS.Common.Core</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SccProjectName>
</SccProjectName>
<SccLocalPath>
</SccLocalPath>
<SccAuxPath>
</SccAuxPath>
<SccProvider>
</SccProvider>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</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\DTSConfig.cs" />
<Compile Include="DTSConstants.cs" />
<Compile Include="EventManager\EventManager.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" />
<None Include="Design\DTS.Common.CoreClassDiagram.cd" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DTS.Common.Utilities\DTS.Common.Utilities.csproj">
<Project>{03EACE47-EA59-44AC-B49D-956E4DC4D618}</Project>
<Name>DTS.Common.Utilities</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
<PropertyGroup>
<PreBuildEvent>
</PreBuildEvent>
</PropertyGroup>
<!-- 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>

View File

@@ -0,0 +1,272 @@
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 DTS.Common.Core.Config;
using DTS.Common.Utilities.Logging;
// ReSharper disable RedundantJumpStatement
// ReSharper disable UnusedTypeParameter
// ReSharper disable UnusedMember.Local
// ReSharper disable UnusedParameter.Local
namespace DTS.Common.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>
public AggregateCatalog PluginCatalog { get; set; }
/// <summary>
/// MEF container
/// </summary>
private CompositionContainer PluginContainer { get; set; }
/// <summary>
/// Thread lock
/// </summary>
private static readonly object THREAD_LOCK = new object();
/// <summary>
/// Constructor that intializes catalog and container
/// </summary>
private PluginManager(string appPath)
{
// Create MEF catalog
PluginCatalog = new AggregateCatalog();
DTSConfig.DTSConfigInit(appPath);
// Get plugin folder from App.Config;
var pcsh = (PluginConfigSectionHandler)DTSConfig.GetSection("DTS.Common.Core.PluginLib.Config"); //DTS.Common.Core.PluginLib.Config
if (pcsh == null)
{
APILogger.Log("## Unable to retrieve plugin config data from DTS.Config (DTS.Common.Core.PluginLib.Config)");
throw new Exception("Unable to retrieve plugin config data from DTS.config (DTS.Common.Core.PluginLib.Config)");
}
foreach (FilterHashElement element in pcsh.HashKeys)
{
try
{
var info = new DirectoryInfo(element.Value);
if (!info.Exists)
{
APILogger.Log($"## Plugin directory does not exist: {element.Value}");
throw new IOException($"Plugin directory does not exist: {element.Value}");
}
PluginCatalog.Catalogs.Add(new DirectoryCatalog(element.Value));
}
catch (Exception ex)
{
APILogger.Log(ex);
throw;
}
}
// Create MEF container
PluginContainer = new CompositionContainer(PluginCatalog);
foreach (var catalog in PluginCatalog.Catalogs)
{
var directoryCatalog = catalog as DirectoryCatalog;
if (directoryCatalog == null)
{
APILogger.Log("## directory catalog is null");
continue;
}
var pluginDir = directoryCatalog.FullPath;
var files = new DirectoryInfo(pluginDir).GetFiles("*.dll");
foreach (var assembly in files.Where(f => !f.Name.StartsWith("DTS.Common") && !f.Name.StartsWith("C1") && !f.Name.StartsWith("Xceed")))
{
var assemblyName = pluginDir + @"\" + assembly.Name;
//var assemblyName = $"{pluginDir}{assembly.Name}";
// verift assembly exists and matches requested paramaters
if (!File.Exists(assemblyName))
{
APILogger.Log($"## File Not Found!: {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
try
{
var asm = Assembly.LoadFrom(assemblyName);
}
catch (Exception ex)
{
APILogger.Log("## Failed to load assembly:", ex);
throw;
}
}
}
}
public List<Assembly> GetPluginList<T>() where T : class
{
var assemblyList = new List<Assembly>();
var manager = GetPluginManager(string.Empty);
foreach (var catalog in manager.PluginCatalog.Catalogs)
{
var directoryCatalog = catalog as DirectoryCatalog;
if (directoryCatalog == null) continue;
assemblyList.AddRange(directoryCatalog.Parts.Select(part => ReflectionModelServices.GetPartType(part).Value.Assembly).Distinct().ToList());
}
return assemblyList;
}
/// <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(string.Empty).PluginContainer.GetExport<T>();
return export?.Value;
}
/// <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(configPluginSetting);
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) continue;
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(string.Empty);
return manager.PluginContainer.GetExports<T>();
}
/// <summary>
/// Returns static singleton reference to plugin manager class
/// </summary>
/// <returns>plugin class</returns>
public static PluginManager GetPluginManager(string appPath)
{
if (!string.IsNullOrWhiteSpace(appPath))
{
var directoryInfo = new DirectoryInfo(appPath);
}
lock (THREAD_LOCK)
{
if (_pluginManager != null)
{
foreach (var catalog in _pluginManager.PluginCatalog.Catalogs)
{
var directoryCatalog = catalog as DirectoryCatalog;
if (directoryCatalog == null) continue;
}
}
return _pluginManager ?? (_pluginManager = new PluginManager(appPath));
}
}
/// <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)
{
APILogger.Log("## null directoryCatalog");
continue;
}
var pluginDir = directoryCatalog.FullPath;
// get name of assembly
var baseName = args.Name.Split(new[] { ',' })[0];
var assemblyName = $"{pluginDir}\\{baseName}.dll";
// verift assembly exists and matches requested paramaters
if (!File.Exists(assemblyName))
{
APILogger.Log($"## assembly does not exist: {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)
{
APILogger.Log("## assembly info is incomplete");
continue;
}
// Load assembly
try
{
var asm = Assembly.LoadFrom(assemblyName);
return asm;
}
catch (Exception ex)
{
APILogger.Log("## failed to load", ex);
throw;
}
}
return null;
}
}
}

View 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("DTS.Common.Core")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DTS.Common.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")]

Binary file not shown.

View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/></startup></configuration>

View File

@@ -0,0 +1,100 @@
using DTS.Common.Utilities.Logging;
using System;
using System.Configuration;
using System.Linq;
// ReSharper disable InconsistentNaming
// ReSharper disable EmptyConstructor
namespace DTS.Common.Core.Config
{
public static class DTSConfig
{
private static string AltConfigPath;
public static string AltConfigPathGet()
{
lock (MyLock)
{
return AltConfigPath;
}
}
public static void AltConfigPathSet(string path)
{
lock (MyLock)
{
AltConfigPath = path;
}
}
// static constructor
static DTSConfig()
{
}
public static void DTSConfigInit(string path)
{
SetAltConfigPath(path);
}
private static object MyLock = new object();
/// <summary>
/// Static variable to hold alternate configuration file
/// </summary>
private static Configuration AltConfig;
public static Configuration GetAltConfig()
{
lock (MyLock)
{
return AltConfig;
}
}
/// <summary>
/// Static variable to hold alternate configuration file
/// </summary>
/// <history>
///
/// </history>
public static void SetAltConfigPath(string path)
{
lock (MyLock)
{
AltConfigPath = path;
var dtsConfig = new ExeConfigurationFileMap
{
ExeConfigFilename = string.IsNullOrEmpty(AltConfigPath) ? DTSConstants.CustomConfigPath : AltConfigPath
};
AltConfig = ConfigurationManager.OpenMappedExeConfiguration(dtsConfig, ConfigurationUserLevel.None, true);
}
}
/// <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 = AltConfig.AppSettings.Settings.Cast<KeyValueConfigurationElement>().FirstOrDefault(setting => setting.Key == key);
if (appSetting == null)
{
APILogger.Log(
$"## AltConfig.AppSettings.Settings.Cast<KeyValueConfigurationElement>().FirstOrDefault(setting => setting.Key == key) is null for 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)
{
var section = AltConfig.GetSection(sectionName);
if (section == null)
{
APILogger.Log($"## AltConfig.GetSection(sectionName) is null for sectionName={sectionName}");
}
return section;
}
}
}

View File

@@ -0,0 +1,108 @@
<?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>DTS.Common.Core</RootNamespace>
<AssemblyName>DTS.Common.Core</AssemblyName>
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SccProjectName>
</SccProjectName>
<SccLocalPath>
</SccLocalPath>
<SccAuxPath>
</SccAuxPath>
<SccProvider>
</SccProvider>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
</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\DTSConfig.cs" />
<Compile Include="DTSConstants.cs" />
<Compile Include="EventManager\EventManager.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" />
<None Include="Design\DTS.Common.CoreClassDiagram.cd" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\DTS.Common.Utilities\DTS.Common.Utilities.csproj">
<Project>{03EACE47-EA59-44AC-B49D-956E4DC4D618}</Project>
<Name>DTS.Common.Utilities</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>
</PostBuildEvent>
</PropertyGroup>
<PropertyGroup>
<PreBuildEvent>
</PreBuildEvent>
</PropertyGroup>
<!-- 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>

View File

@@ -0,0 +1,9 @@
// ReSharper disable InconsistentNaming
namespace DTS.Common.Core
{
public static class DTSConstants
{
public const string CustomConfigPath = @"C:\dev\DTS.Viewer\bin\Debug\DTS.Viewer.exe.config";
public const string ViewerConfigPath = @"C:\dev\DTS.Viewer\bin\Debug\DTS.Viewer.exe.config";
}
}

View File

@@ -0,0 +1,139 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1">
<Class Name="DTS.Common.Core.Config.DTSConfig" Collapsed="true">
<Position X="0.5" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AIAQAAAEAACAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAIA=</HashCode>
<FileName>Config\DTSConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.Core.DTSConstants" Collapsed="true">
<Position X="2.25" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAACAAAAAAAAAAAAAAAAAAAAAAgAAAAA=</HashCode>
<FileName>DTSConstants.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.Core.EventManager.EventManager" Collapsed="true">
<Position X="4" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAIIAAACAAGAEAACAAAAAACAAAAQAAAAABAAAA=</HashCode>
<FileName>EventManager\EventManager.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.Core.EventManager.EventMetaData&lt;T&gt;" Collapsed="true">
<Position X="5.75" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA=</HashCode>
<FileName>EventManager\EventManager.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.Core.PluginLib.PluginConfig" Collapsed="true">
<Position X="4" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAgAAAIAAAAAAAAAAAAAA=</HashCode>
<FileName>PluginLib\PluginConfig.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.Core.PluginLib.PluginConfigData" Collapsed="true">
<Position X="5.75" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAA=</HashCode>
<FileName>PluginLib\PluginConfigData.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.Core.PluginLib.PluginConfigSectionHandler" Collapsed="true">
<Position X="0.5" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>PluginLib\PluginConfigSectionHandler.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.Core.PluginLib.FilterHashKeyCollection" Collapsed="true">
<Position X="2.25" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAACAAAAAAAAAAAACAAAAAAAAAABAAAAAAAAAAAAAAA=</HashCode>
<FileName>PluginLib\PluginConfigSectionHandler.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.Core.PluginLib.FilterHashElement" Collapsed="true">
<Position X="0.5" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAgAAAAAAA=</HashCode>
<FileName>PluginLib\PluginConfigSectionHandler.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.Core.PluginLib.PluginManager" Collapsed="true">
<Position X="2.25" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AEAABAAAAAAEAACAAAMAAAAAAAAAAAAAAgAAAAAAAAA=</HashCode>
<FileName>PluginLib\PluginManager.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.Core.ServiceManager.ServiceManager" Collapsed="true">
<Position X="4" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>gAAAAAAAAAAAAABAAEAAAAABAAAAAAAAAAAAAAFAAAA=</HashCode>
<FileName>ServiceManager\ServiceManager.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.Core.ServiceManager.ServicePublishedEvent" Collapsed="true" BaseTypeListCollapsed="true">
<Position X="5.75" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAA=</HashCode>
<FileName>ServiceManager\ServicePublishedEvent.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" Collapsed="true" />
</Class>
<Class Name="DTS.Common.Core.Settings.SettingsChangedEventArgs&lt;TKey, TItem&gt;" Collapsed="true">
<Position X="0.5" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAQAAAEAAAAEAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Settings\SettingsChangedEventArgs.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.Core.Settings.SettingsCollection&lt;TKey, TItem&gt;" Collapsed="true" BaseTypeListCollapsed="true">
<Position X="2.25" Y="3.5" Width="1.5" />
<TypeIdentifier>
<HashCode>CAIAAAAAAAAEABAQCAAABAQAABAAAAAEAAAgAABwKAA=</HashCode>
<FileName>Settings\SettingsCollection.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" Collapsed="true" />
</Class>
<Interface Name="DTS.Common.Core.ServiceManager.IServicePublishedEvent" Collapsed="true">
<Position X="0.5" Y="4.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAA=</HashCode>
<FileName>ServiceManager\IServicePublishedEvent.cs</FileName>
</TypeIdentifier>
</Interface>
<Enum Name="DTS.Common.Core.EventManager.EventDiagnosticType" Collapsed="true">
<Position X="2.25" Y="5.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAABAAAAAAAAAAAAAEIACAAAAAAABAAAA=</HashCode>
<FileName>EventManager\EventManager.cs</FileName>
</TypeIdentifier>
</Enum>
<Enum Name="DTS.Common.Core.Settings.ChangeSettingType" Collapsed="true">
<Position X="0.5" Y="5.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAIAAAAAAAAAAABAABAABAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Settings\SettingsChangedEventArgs.cs</FileName>
</TypeIdentifier>
</Enum>
<Delegate Name="DTS.Common.Core.EventManager.SubscriberCallbackDelegate&lt;T&gt;" Collapsed="true">
<Position X="2.25" Y="6.75" Width="1.5" />
<TypeIdentifier>
<HashCode>BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>EventManager\EventManager.cs</FileName>
</TypeIdentifier>
</Delegate>
<Delegate Name="DTS.Common.Core.EventManager.DiagnosticCallbackDelegate" Collapsed="true">
<Position X="0.5" Y="6.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAACAAEAAAAAAAAAEAAAABAAAAAAAAAAAAAA=</HashCode>
<FileName>EventManager\EventManager.cs</FileName>
</TypeIdentifier>
</Delegate>
<Font Name="Segoe UI" Size="9" />
</ClassDiagram>

View File

@@ -0,0 +1,193 @@
using System;
using System.Collections.Generic;
using System.Reflection;
namespace DTS.Common.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?.Method);
}
}
/// <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 =>
{
return p is EventMetaData<T> eventMetaData && 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 = $"{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
}
internal class EventMetaData<T> where T : class
{
public Predicate<T> EventFilter { get; set; }
public SubscriberCallbackDelegate<T> Callback { get; set; }
}
}

View File

@@ -0,0 +1,27 @@
using DTS.Common.Core.Config;
// ReSharper disable InconsistentNaming
namespace DTS.Common.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 DTSPlugins = "DTSPlugins";
/// <summary>
/// concatenate plugin name from app setting with class exporter name for DTS plugins
/// </summary>
/// <param name="setting"></param>
/// <returns></returns>
public static string GetDTSPluginsSetting(string setting)
{
return DTSConfig.GetAppSetting(DTSPlugins) + "." + setting;
}
}
}

View File

@@ -0,0 +1,14 @@
using System.Xml.Serialization;
namespace DTS.Common.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;
}
}

View File

@@ -0,0 +1,46 @@
using System.Configuration;
namespace DTS.Common.Core.PluginLib
{
/// <summary>
/// Support class that parses data from DTS.Common.Core.PluginLib.Config configuration section
/// </summary>
public class PluginConfigSectionHandler : ConfigurationSection
{
[ConfigurationProperty("PluginFolders")]
public FilterHashKeyCollection HashKeys => (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] => (FilterHashElement)BaseGet(idx);
}
public class FilterHashElement : ConfigurationElement
{
[ConfigurationProperty("key", DefaultValue = "", IsKey = true, IsRequired = true)]
public string Key
{
get => (string)base["key"];
set => base["key"] = value;
}
[ConfigurationProperty("value", DefaultValue = "", IsKey = false, IsRequired = false)]
public string Value
{
get => (string)base["value"];
set => base["value"] = value;
}
}
}

View File

@@ -0,0 +1,272 @@
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 DTS.Common.Core.Config;
using DTS.Common.Utilities.Logging;
// ReSharper disable RedundantJumpStatement
// ReSharper disable UnusedTypeParameter
// ReSharper disable UnusedMember.Local
// ReSharper disable UnusedParameter.Local
namespace DTS.Common.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>
public AggregateCatalog PluginCatalog { get; set; }
/// <summary>
/// MEF container
/// </summary>
private CompositionContainer PluginContainer { get; set; }
/// <summary>
/// Thread lock
/// </summary>
private static readonly object THREAD_LOCK = new object();
/// <summary>
/// Constructor that intializes catalog and container
/// </summary>
private PluginManager(string appPath)
{
// Create MEF catalog
PluginCatalog = new AggregateCatalog();
DTSConfig.DTSConfigInit(appPath);
// Get plugin folder from App.Config;
var pcsh = (PluginConfigSectionHandler)DTSConfig.GetSection("DTS.Common.Core.PluginLib.Config"); //DTS.Common.Core.PluginLib.Config
if (pcsh == null)
{
APILogger.Log("## Unable to retrieve plugin config data from DTS.Config (DTS.Common.Core.PluginLib.Config)");
throw new Exception("Unable to retrieve plugin config data from DTS.config (DTS.Common.Core.PluginLib.Config)");
}
foreach (FilterHashElement element in pcsh.HashKeys)
{
try
{
var info = new DirectoryInfo(element.Value);
if (!info.Exists)
{
APILogger.Log($"## Plugin directory does not exist: {element.Value}");
throw new IOException($"Plugin directory does not exist: {element.Value}");
}
PluginCatalog.Catalogs.Add(new DirectoryCatalog(element.Value));
}
catch (Exception ex)
{
APILogger.Log(ex);
throw;
}
}
// Create MEF container
PluginContainer = new CompositionContainer(PluginCatalog);
foreach (var catalog in PluginCatalog.Catalogs)
{
var directoryCatalog = catalog as DirectoryCatalog;
if (directoryCatalog == null)
{
APILogger.Log("## directory catalog is null");
continue;
}
var pluginDir = directoryCatalog.FullPath;
var files = new DirectoryInfo(pluginDir).GetFiles("*.dll");
foreach (var assembly in files.Where(f => !f.Name.StartsWith("DTS.Common") && !f.Name.StartsWith("C1") && !f.Name.StartsWith("Xceed")))
{
var assemblyName = pluginDir + @"\" + assembly.Name;
//var assemblyName = $"{pluginDir}{assembly.Name}";
// verift assembly exists and matches requested paramaters
if (!File.Exists(assemblyName))
{
APILogger.Log($"## File Not Found!: {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
try
{
var asm = Assembly.LoadFrom(assemblyName);
}
catch (Exception ex)
{
APILogger.Log("## Failed to load assembly:", ex);
throw;
}
}
}
}
public List<Assembly> GetPluginList<T>() where T : class
{
var assemblyList = new List<Assembly>();
var manager = GetPluginManager(string.Empty);
foreach (var catalog in manager.PluginCatalog.Catalogs)
{
var directoryCatalog = catalog as DirectoryCatalog;
if (directoryCatalog == null) continue;
assemblyList.AddRange(directoryCatalog.Parts.Select(part => ReflectionModelServices.GetPartType(part).Value.Assembly).Distinct().ToList());
}
return assemblyList;
}
/// <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(string.Empty).PluginContainer.GetExport<T>();
return export?.Value;
}
/// <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(configPluginSetting);
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) continue;
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(string.Empty);
return manager.PluginContainer.GetExports<T>();
}
/// <summary>
/// Returns static singleton reference to plugin manager class
/// </summary>
/// <returns>plugin class</returns>
public static PluginManager GetPluginManager(string appPath)
{
if (!string.IsNullOrWhiteSpace(appPath))
{
var directoryInfo = new DirectoryInfo(appPath);
}
lock (THREAD_LOCK)
{
if (_pluginManager != null)
{
foreach (var catalog in _pluginManager.PluginCatalog.Catalogs)
{
var directoryCatalog = catalog as DirectoryCatalog;
if (directoryCatalog == null) continue;
}
}
return _pluginManager ?? (_pluginManager = new PluginManager(appPath));
}
}
/// <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)
{
APILogger.Log("## null directoryCatalog");
continue;
}
var pluginDir = directoryCatalog.FullPath;
// get name of assembly
var baseName = args.Name.Split(new[] { ',' })[0];
var assemblyName = $"{pluginDir}\\{baseName}.dll";
// verift assembly exists and matches requested paramaters
if (!File.Exists(assemblyName))
{
APILogger.Log($"## assembly does not exist: {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)
{
APILogger.Log("## assembly info is incomplete");
continue;
}
// Load assembly
try
{
var asm = Assembly.LoadFrom(assemblyName);
return asm;
}
catch (Exception ex)
{
APILogger.Log("## failed to load", ex);
throw;
}
}
return null;
}
}
}

View 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("DTS.Common.Core")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("DTS.Common.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")]

View File

@@ -0,0 +1,20 @@
using System;
namespace DTS.Common.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; }
}
}

View File

@@ -0,0 +1,141 @@
using System;
using System.Collections.Generic;
// ReSharper disable InconsistentNaming
namespace DTS.Common.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($"{typeof(T).Name}: has already been published");
}
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($"{t.Name}: has already been published");
}
}
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($"{typeof(T).Name}: has not been published");
}
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
});
}
}
}

View File

@@ -0,0 +1,28 @@
using System;
namespace DTS.Common.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;
}
}
}

View File

@@ -0,0 +1,84 @@
using System;
namespace DTS.Common.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
}
}

View File

@@ -0,0 +1,213 @@
using System;
using System.Collections;
using System.Collections.Generic;
namespace DTS.Common.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>
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);
}
/// <inheritdoc />
/// <summary>
/// Returns all keys in collection
/// </summary>
public ICollection<TKey> Keys => _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 => _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 => _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 => _items.Count;
/// <summary>
/// Returns true if readonly collection
/// </summary>
public bool IsReadOnly => 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)
{
CollectionItemPropertyChanged?.Invoke(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)
{
CollectionItemPropertyChanged?.Invoke(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)
{
CollectionItemPropertyChanged?.Invoke(this, new SettingsChangedEventArgs<TKey, TItem>(changeType, key, item));
}
#endregion
}
}

View File

@@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = "")]

View File

@@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.8", FrameworkDisplayName = ".NET Framework 4.8")]

View File

@@ -0,0 +1 @@
12

View File

@@ -0,0 +1 @@
12

View File

@@ -0,0 +1,142 @@
/*
* IArmable.cs
*
* Copyright © 2010
* Diversified Technical Systems, Inc.
* All Rights Reserved.
*/
namespace DTS.DAS.Concepts
{
/// <summary>
/// different possible arm modes
/// </summary>
public enum AvailableArmModes
{
LowPower,
CircularBuffer,
};
/// <summary>
/// different possible armstatus
/// </summary>
public enum ArmStatus
{
Disarming,
Disarmed,
Arming,
Armed,
Recording, // Extra statuses (chuck's mail)
}
///
/// <summary>
/// Formal description of the ability to "arm".
/// </summary>
///
public interface IArmable
{
void Arm();
void Disarm();
ArmStatus ArmStatus { get; }
AvailableArmModes ArmMode { get; }
}
}
//Like Rollin said, NGI will (for now) be orphaned. NASCAR is in for sure. TSR6DX is really TSRPRO, I think. RateTestTSR==BlastTestTSR and needs to be flattened. TSR==TSRBasic. The missing one in that list is HEADSII.
//NASCAR is 3 16-bit channels using a 216 daughterboard.
//TSRPRO is 6 channels, 3 16-bit on a 216 daughterboard, 3 12-bit on the 215 motherboard
//BlastTestTSR is 7 channels, 4 12-bit on the 215 motherboard, 3 16-bit on a hacked daughterboard
//TSRBasic is 3 12-bit channels on the 215 motherboard
//HEADSII is 7 12-bit channels on the 221 board
//The other missing component to some of what you sent earlier is that some of these systems have multiple sample rates. BlastTestTSR will have the 4 12-bit channels @ 40ksps and the 3 16-bit channels @ 1ksps. NGI had 2 24-bit channels @ 1ksps and 2 16-bit (?? can't remember for sure) channels @ 1sps. As it stands now we have the lower level download code just interpolate slow data to fast data and then everything has the "same" sample rate at the upper level, but it might be nice to deal with it more formally since that creates some funny edge cases we have to deal with by limiting the download to occur in sample number chunks that are a multiple of the fast rate divided by the slow rate.
//On 8/12/2010 11:12 AM, Paul Hrissikopoulos wrote:
//> By the way, the types that the switches currently in the TSR2 code seem to think important are:
//>
//> TSRModel.NASCARIDR:
//> TSRModel.TSR6DX:
//> TSRModel.RateTestTSR:
//> TSRModel.BlastTSR:
//> TSRModel.TSR:
//> TSRModel.NGIPrototype:
//>
//> Are we going to want all of those? Some of those? Those and then some?
//>
//> On 8/12/2010 11:07 AM, Paul Hrissikopoulos wrote:
//>> I guess in theory the software should be able to deal with the multiplicity of device types as it sees fit -- some code, definitely including parts of the UI, will need to be able to actively discriminate between types before doing something type-specific, but I think the hope is that the bulk should be able to use it in a more generic sense (arm the same, download the same, realtime the same, etc.). But still maybe that's a valid point -- do we foresee a ton of cases where we'll be doing interface is/as and/or typefield checks before doing something?
//>>
//>> On 8/12/2010 10:50 AM, Tadd Seiff wrote:
//>>> I like this.
//>>>
//>>> My approach at the moment is immediately how to use this as a HEADS device. My understanding is that the device will surface through the factory which will populate things such as TSR.Channel[] Channels which can then be accessed safely only with RunTime checks like if (HEADS == unit.TSRModel) {...}. Does this put us in the same position being at the mercy of switch statements at a higher level? This is just my knee-jerk reaction.
//>>>
//>>> On 8/12/2010 10:08 AM, Paul Hrissikopoulos wrote:
//>>>> My reordering is attached. Search it for "?" for some open questions. Please let me know if you think I'm missing anything major (or minor) or am entirely on the wrong track.
//>>>>
//>>>> On 8/9/2010 10:26 PM, Rollin White wrote:
//>>>>> Here's an update with a channel class.
//>>>>>
//>>>>> Please voice concerns, opinions, etc. This is just my simple view of the task.
//>>>>>
//>>>>> On 8/9/2010 3:02 PM, Rollin White wrote:
//>>>>>> Here's my first cut at the interface description for the next generation TSR class. The interface is meant to describe the features common to all models.
//>>>>>>
//>>>>>> In addition to what's here, there needs to be significant definition of the channel class. Finally, there are probably a few interfaces that need to be defined that class implementers would optionally implement. For example, ISupportsDynamicEventLength.
//>>>>>>
//>>>>>> This is simply a starting point. Comments welcome.
//>>>>
//>>>
//>>
//>
//>
//--
//Chuck Gillen-O'Neel
//Diversified Technical Systems, Inc.
//909 Electric Avenue, Suite 206
//Seal Beach, CA 90740
//Telephone: (562) 493-0158
//Email: chuck.go@dtsweb.com
// My comments:
// * For sensitivity we should either have mv/count and eu/mv for each channel OR have eu/count for each channel. Obviously the former is more flexible, but also a little more complicated and maybe unneeded for 95-99% of TSR/HEADS applications.
// * OffsetCounts in IChannel should be signed. We nearly always need to make offsets signed. I'm speaking from my own mistakes here ... !!! :)
// * We need to think about the arm states a bit more. There have been a couple of cases where having a Disarming state, in addition to Disarmed, has been nice.
// * For GPIOs we might as well surface (and extend the firmware a bit to support this) the fact that IOs can be inputs as well as high/low outputs. So, rather than just returning a bool we might want to return a state enum. It's already there in the interface for SetGPIO since the GPIOPin.Direction enum has input and output and if it's set to input the State parameter is effectively a no-op.
// * The question of a good interface for Calibration is still unanswered. The interface as shown is obviously fine for doing those three readings, but I'm not sure how truly useful that is in a generic sense. I have a feeling that this is a place where we'll be hooking in model checks, etc. etc. Maybe that's okay and can be limited to the cal software.
//On 8/12/2010 10:50 AM, Tadd Seiff wrote:
//> I like this.
//>
//> My approach at the moment is immediately how to use this as a HEADS device. My understanding is that the device will surface through the factory which will populate things such as TSR.Channel[] Channels which can then be accessed safely only with RunTime checks like if (HEADS == unit.TSRModel) {...}. Does this put us in the same position being at the mercy of switch statements at a higher level? This is just my knee-jerk reaction.
//>
//> On 8/12/2010 10:08 AM, Paul Hrissikopoulos wrote:
//>> My reordering is attached. Search it for "?" for some open questions. Please let me know if you think I'm missing anything major (or minor) or am entirely on the wrong track.
//>>
//>> On 8/9/2010 10:26 PM, Rollin White wrote:
//>>> Here's an update with a channel class.
//>>>
//>>> Please voice concerns, opinions, etc. This is just my simple view of the task.
//>>>
//>>> On 8/9/2010 3:02 PM, Rollin White wrote:
//>>>> Here's my first cut at the interface description for the next generation TSR class. The interface is meant to describe the features common to all models.
//>>>>
//>>>> In addition to what's here, there needs to be significant definition of the channel class. Finally, there are probably a few interfaces that need to be defined that class implementers would optionally implement. For example, ISupportsDynamicEventLength.
//>>>>
//>>>> This is simply a starting point. Comments welcome.
//>>
//>
//--
//Chuck Gillen-O'Neel
//Diversified Technical Systems, Inc.
//909 Electric Avenue, Suite 206
//Seal Beach, CA 90740
//Telephone: (562) 493-0158
//Email: chuck.go@dtsweb.com

View File

@@ -0,0 +1,682 @@
using DTS.Common.Enums.Sensors;
using System;
using System.Collections.Generic;
using System.Text;
namespace DTS.Common.DAS.Concepts
{
public class LinearizationFormula
{
private bool _bIsValid;
public bool IsValid() { return _bIsValid; }
public void MarkValid(bool bValid)
{
_bIsValid = bValid;
}
// Translation
public NonLinearSLICEWareStyles NonLinearSliceWareStyle
{
get => (NonLinearSLICEWareStyles)NonLinearStyle;
set => NonLinearStyle = (NonLinearStyles)value;
}
public NonLinearStyles NonLinearStyle { get; set; } = NonLinearStyles.Polynomial; // Dont make the default style one that locks a specific zero-method FB 10323
public double PolynomialSensitivity { get; set; } = 1D;
public double LinearizationExponent { get; set; } = 1D;
/// <summary>
/// THIS IS MM/V, (UI has already been updated, we need to update the variable name)
/// </summary>
private double _mmPerMV;
public double MMPerV
{
get => _mmPerMV;
set => _mmPerMV = value;
}
public double MVAt0MM { get; set; }
public double Slope { get; set; }
public double Intercept { get; set; }
public double CalibrationFactor { get; set; }
public double ZeroPositionIntercept { get; set; }
public LinearizationFormula()
{
ZeroPositionIntercept = 0D;
CalibrationFactor = 0D;
Intercept = 0D;
_coefficients = new List<double>(new double[] { 0, 0, 0, 0 });
_exponents = new List<double>(new double[] { 0, 1, 2, 3 });
}
public LinearizationFormula(LinearizationFormula copy)
{
UsemVOverVForPolys = copy.UsemVOverVForPolys;
_bIsValid = copy._bIsValid;
_coefficients = new List<double>(copy._coefficients.ToArray());
_exponents = new List<double>(copy._exponents.ToArray());
Intercept = copy.Intercept;
LinearizationExponent = copy.LinearizationExponent;
_mmPerMV = copy._mmPerMV;
MVAt0MM = copy.MVAt0MM;
Slope = copy.Slope;
NonLinearStyle = copy.NonLinearStyle;
_coefficients = new List<double>(copy._coefficients);
_exponents = new List<double>(copy._exponents);
PolynomialSensitivity = copy.PolynomialSensitivity;
ZeroPositionIntercept = copy.ZeroPositionIntercept;
CalibrationFactor = copy.CalibrationFactor;
}
public double GetCoefficient(double exponent)
{
for (var i = 0; i < _exponents.Count && i < _coefficients.Count; i++)
{
if (_exponents[i] == exponent) { return _coefficients[i]; }
}
return 0;
}
public void SetCoefficient(double exponent, double coefficient)
{
for (var i = 0; i < _exponents.Count && i < _coefficients.Count; i++)
{
if (_exponents[i] == exponent) { _coefficients[i] = coefficient; return; }
}
}
public double GetLinearizedValue(double input, double excitation)
{
if (NonLinearStyle != NonLinearStyles.Polynomial && input <= 0)
{
//ir-tracc should never be < 0, however we may get readings less than zero due to
//noise and other factors, treat these as positive near to zero
input = .001;
}
//first linearize
input /= 1000D;//assume input is in mV and we want it in Volts
input = Math.Pow(input, LinearizationExponent);
switch (NonLinearStyle)
{
case NonLinearStyles.IRTraccDiagnosticsZero:
return GetEUDiagnosticsZero(input);
case NonLinearStyles.IRTraccManual:
return GetEUIRTraccManual(input);
case NonLinearStyles.IRTraccZeroMMmV:
return GetEUZeroMMmV(input);
case NonLinearStyles.IRTraccAverageOverTime:
return GetEUAverageOverTime(input);
case NonLinearStyles.Polynomial:
return GetEUPolynomial(input, excitation);
case NonLinearStyles.IRTraccCalFactor:
return GetEUIRTraccCalFactor(input);
default:
throw new NotSupportedException("unknown format: " + NonLinearStyle);
}
}
private double GetEUIRTraccCalFactor(double volts)
{
return volts * CalibrationFactor + ZeroPositionIntercept;
}
private double GetEUIRTraccManual(double volts)
{
return (volts - Intercept) / Slope;
}
public bool UsemVOverVForPolys { get; set; }
private double GetEUZeroMMmV(double volts)
{
var input = MVAt0MM / 1000D;
input = Math.Pow(input, LinearizationExponent);
if (double.IsNaN(input) || double.IsNegativeInfinity(input) || double.IsPositiveInfinity(input))
{
return volts * MMPerV;
}
return (volts * MMPerV - MMPerV * input);
}
private List<double> _coefficients = new List<double>();
private List<double> _exponents = new List<double>();
private double GetEUPolynomial(double volts, double excitation)
{
//per J2517
//3.4 Use of the Calibration Coefficients
//The potentiometer assembly should be re-installed in the dummy without any mechanical adjustment of the
//potentiometer. Prior to a crash test, the original zero offset level must be preserved by either not zeroing the
//potentiometer (by signal conditioning or post-processing) or the amount that was zeroed must be added during postprocessing.
//During the test the absolute voltage output time history should be recorded. This voltage signal is then
//converted to engineering units by:
//1. Convert voltage signal to mV/V at the sensor. This is the sensor reading S.
//2. Convert the sensor reading S to displacement D by using the equation:
//D = A*S^3 + B*S^2 + C*S + M (Eq. 2)
//where:
//D is the displacement relative to the thorax design position in mm
//S is the sensor output reading in mV/V
//A, B, C, and M are the calibration coefficients
//NOTE: Make sure to use sufficient significant digits on all coefficients to assure accuracy of the conversion to
//engineering units. It is recommended to use 5 significant digits (example 0.000012345).
//double mV = volts * 1000D;
//double gain = 1D;
//mV = mV / (gain * excitation);
//if (0 != PolynomialSensitivity && 1!= PolynomialSensitivity) { mV /= PolynomialSensitivity; }
//double eu = 0D;
//for (int i = 0; i < _coefficients.Count && i < _exponents.Count; i++)
//{
// eu += _coefficients[i] * Math.Pow(mV, _exponents[i]);
//}
//return eu;
//CHANGED FOR GM TESTING
if (0 != PolynomialSensitivity && 1 != PolynomialSensitivity)
{
volts /= PolynomialSensitivity;
}
var voltsOverV = 0D;
if (UsemVOverVForPolys)
{
//convert to mV first
voltsOverV = (volts * 1000D) / excitation;
}
else
{
//used by GM
voltsOverV = volts / excitation;
}
double eu = 0;
for (var i = 0; i < _coefficients.Count && i < _exponents.Count; i++)
{
if (_exponents[i] != 0)
{
eu += _coefficients[i] * Math.Pow(voltsOverV, _exponents[i]);
}
else
{
eu += _coefficients[i];
}
}
return eu;
}
/// <summary>
/// MvAt0MM set at diagnostics
/// </summary>
/// <param name="volts"></param>
/// <returns></returns>
private double GetEUDiagnosticsZero(double volts)
{
//double input = MVAt0MM/1000D;
//input = System.Math.Pow(input,LinearizationExponent);
var input = double.NaN;
if (double.IsNaN(input) || double.IsPositiveInfinity(input) || double.IsNegativeInfinity(input))
{
return volts * MMPerV;
}
return volts * MMPerV - MMPerV * input;
}
/// <summary>
/// MVAt0MM set by diagnostics and then later on at
/// Average Over Time
/// </summary>
/// <param name="volts"></param>
/// <returns></returns>
private double GetEUAverageOverTime(double volts)
{
//double input = MVAt0MM / 1000D;
//input = System.Math.Pow(input, LinearizationExponent);
var input = double.NaN;
if (double.IsNaN(input) || double.IsNegativeInfinity(input) || double.IsPositiveInfinity(input))
{
return volts * MMPerV;
}
return volts * MMPerV - MMPerV * input;
}
public string ToSLICEWareSerializeString()
{
if (!_bIsValid) { return ""; }
var sb = new StringBuilder();
sb.AppendFormat("{0}_", NonLinearStyle);
switch (NonLinearStyle)
{
case NonLinearStyles.IRTraccDiagnosticsZero:
sb.Append(ToIRTraccDiagnosticZeroString());
break;
case NonLinearStyles.IRTraccManual:
sb.Append(ToIRTraccManualString());
break;
case NonLinearStyles.IRTraccZeroMMmV:
sb.Append(ToIRTraccZeroMMmVString());
break;
case NonLinearStyles.IRTraccAverageOverTime:
sb.Append(ToIRTraccAverageOverTimeString());
break;
case NonLinearStyles.Polynomial:
sb.Append(ToSLICEWarePolynomialString());
break;
case NonLinearStyles.IRTraccCalFactor:
throw new NotSupportedException("CalFactor not supported in SLICEWare");
default:
throw new NotSupportedException("unknown type: " + NonLinearStyle);
}
return sb.ToString();
}
/// <summary>
/// serializes to a string of the format "c0xe0 c1xe1...cnxen"
/// this will allow us arbitrary length polynomials and fractional exponents.
/// </summary>
/// <returns></returns>
public string ToSerializeString()
{
if (!_bIsValid) { return ""; }
var sb = new StringBuilder();
sb.AppendFormat("{0}_", NonLinearStyle);
switch (NonLinearStyle)
{
case NonLinearStyles.IRTraccDiagnosticsZero:
sb.Append(ToIRTraccDiagnosticZeroString());
break;
case NonLinearStyles.IRTraccManual:
sb.Append(ToIRTraccManualString());
break;
case NonLinearStyles.IRTraccZeroMMmV:
sb.Append(ToIRTraccZeroMMmVString());
break;
case NonLinearStyles.IRTraccAverageOverTime:
sb.Append(ToIRTraccAverageOverTimeString());
break;
case NonLinearStyles.Polynomial:
sb.Append(ToPolynomialString());
break;
case NonLinearStyles.IRTraccCalFactor:
sb.Append(ToIRTraccCalFactorString());
break;
default:
throw new NotSupportedException("unknown type: " + NonLinearStyle);
}
return sb.ToString();
}
public string ToIRTraccDiagnosticZeroString()
{
return $"{MMPerV.ToString(System.Globalization.CultureInfo.InvariantCulture)}x{LinearizationExponent.ToString(System.Globalization.CultureInfo.InvariantCulture)}";
}
public string ToIRTraccCalFactorString()
{
return $"{CalibrationFactor.ToString(System.Globalization.CultureInfo.InvariantCulture)}x{LinearizationExponent.ToString(System.Globalization.CultureInfo.InvariantCulture)}x{ZeroPositionIntercept.ToString(System.Globalization.CultureInfo.InvariantCulture)}";
}
public void FromIRTraccCalFactorString(string s, System.Globalization.CultureInfo culture)
{
var tokens = s.Split('x');
if (tokens.Length < 3) { throw new NotSupportedException("Invalid CalFactor format: " + s); }
CalibrationFactor = double.Parse(tokens[0], culture);
LinearizationExponent = double.Parse(tokens[1], culture);
ZeroPositionIntercept = double.Parse(tokens[2], culture);
}
public void FromIRTraccDiagnosticZeroString(string s, System.Globalization.CultureInfo culture)
{
var tokens = s.Split('x');
if (tokens.Length < 2) { throw new NotSupportedException("Invalid DiagnosticsZero format: " + s); }
MMPerV = double.Parse(tokens[0], culture);
LinearizationExponent = double.Parse(tokens[1], culture);
}
public string ToIRTraccManualString()
{
return $"{Slope.ToString(System.Globalization.CultureInfo.InvariantCulture)}x{Intercept.ToString(System.Globalization.CultureInfo.InvariantCulture)}x{LinearizationExponent.ToString(System.Globalization.CultureInfo.InvariantCulture)}";
}
public void FromIRTraccManualString(string s, System.Globalization.CultureInfo culture)
{
var tokens = s.Split('x');
if (tokens.Length < 3) { throw new NotSupportedException("Invalid IRTraccManual format: " + s); }
Slope = double.Parse(tokens[0], culture);
Intercept = double.Parse(tokens[1], culture);
LinearizationExponent = double.Parse(tokens[2], culture);
}
public string ToIRTraccZeroMMmVString()
{
return $"{MMPerV.ToString(System.Globalization.CultureInfo.InvariantCulture)}x{MVAt0MM.ToString(System.Globalization.CultureInfo.InvariantCulture)}x{LinearizationExponent.ToString(System.Globalization.CultureInfo.InvariantCulture)}";
}
public string ToSLICEWarePolynomialString()
{
//SLICEWare is the reverse order of our DataPRO Database
var sb = new StringBuilder();
for (var i = _exponents.Count - 1; i >= 0; i--)
{
if (i != _exponents.Count - 1) { sb.Append(","); }
sb.AppendFormat("{0}x{1}", _coefficients[i].ToString(System.Globalization.CultureInfo.InvariantCulture),
_exponents[i].ToString(System.Globalization.CultureInfo.InvariantCulture));
}
sb.AppendFormat(",S={0}", PolynomialSensitivity.ToString(System.Globalization.CultureInfo.InvariantCulture));
return sb.ToString();
}
public string ToPolynomialString()
{
var sb = new StringBuilder();
for (var i = 0; i < _coefficients.Count && i < _exponents.Count; i++)
{
if (i > 0) { sb.Append(","); }
sb.AppendFormat("{0}x{1}", _coefficients[i].ToString(System.Globalization.CultureInfo.InvariantCulture),
_exponents[i].ToString(System.Globalization.CultureInfo.InvariantCulture));
}
sb.AppendFormat(",S={0},mV={1}",
PolynomialSensitivity.ToString(System.Globalization.CultureInfo.InvariantCulture),
UsemVOverVForPolys.ToString(System.Globalization.CultureInfo.InvariantCulture));
return sb.ToString();
}
public double[] PolynomialCoefficients
{
get => _coefficients.ToArray();
set => _coefficients = new List<double>(value);
}
public double[] PolynomialExponents
{
get => _exponents.ToArray();
set => _exponents = new List<double>(value);
}
public string ToIRTraccAverageOverTimeString()
{
return $"{MMPerV.ToString(System.Globalization.CultureInfo.InvariantCulture)}x{LinearizationExponent.ToString(System.Globalization.CultureInfo.InvariantCulture)}";
}
public void FromIRTraccAverageOverTimeString(string s, System.Globalization.CultureInfo culture)
{
var tokens = s.Split('x');
if (tokens.Length < 2) { throw new NotSupportedException("Invalid IRTRaccAverageOverTime format: " + s); }
MMPerV = double.Parse(tokens[0], culture);
LinearizationExponent = double.Parse(tokens[1], culture);
}
public void FromIRTraccZeroMMmVString(string s, System.Globalization.CultureInfo culture)
{
var tokens = s.Split('x');
if (tokens.Length < 3) { throw new NotSupportedException("Invalid IRTraccZeroMMmV format: " + s); }
MMPerV = double.Parse(tokens[0], culture);
MVAt0MM = double.Parse(tokens[1], culture);
LinearizationExponent = double.Parse(tokens[2], culture);
}
public void FromPolynomialString(string s, System.Globalization.CultureInfo culture)
{
_coefficients.Clear();
_exponents.Clear();
var tokens = s.Split(',');
foreach (var t in tokens)
{
var subtokens = t.Split('x');
if (2 == subtokens.Length)
{
if (double.TryParse(subtokens[0], System.Globalization.NumberStyles.Float, culture, out var d))
{
_coefficients.Add(d);
_exponents.Add(double.Parse(subtokens[1], culture));
}
else
{
PolynomialSensitivity = double.Parse(subtokens[1], culture);
}
}
else
{
subtokens = t.Split('=');
if (subtokens.Length == 2)
{
switch (subtokens[0])
{
case "S":
PolynomialSensitivity = double.Parse(subtokens[1], culture);
break;
case "mV":
UsemVOverVForPolys = Convert.ToBoolean(subtokens[1], culture);
break;
}
}
}
}
}
public void FromSerializeString(string s, System.Globalization.CultureInfo culture)
{
if (string.IsNullOrEmpty(s)) { _bIsValid = false; return; }
if (s.Equals("1") || s.Equals("0") || s.Equals("1 ")) { _bIsValid = false; return; }
var tokens = s.Split('_');
if (tokens.Length < 2) { throw new NotSupportedException("unsupported Linearization Formula Format"); }
var style = (NonLinearStyles)Enum.Parse(typeof(NonLinearStyles), tokens[0], true);
NonLinearStyle = style;
switch (NonLinearStyle)
{
case NonLinearStyles.IRTraccDiagnosticsZero:
FromIRTraccDiagnosticZeroString(tokens[1], culture);
_bIsValid = true;
break;
case NonLinearStyles.IRTraccManual:
FromIRTraccManualString(tokens[1], culture);
_bIsValid = true;
break;
case NonLinearStyles.IRTraccZeroMMmV:
FromIRTraccZeroMMmVString(tokens[1], culture);
_bIsValid = true;
break;
case NonLinearStyles.Polynomial:
FromPolynomialString(tokens[1], culture);
_bIsValid = true;
break;
case NonLinearStyles.IRTraccAverageOverTime:
FromIRTraccAverageOverTimeString(tokens[1], culture);
_bIsValid = true;
break;
case NonLinearStyles.IRTraccCalFactor:
FromIRTraccCalFactorString(tokens[1], culture);
_bIsValid = true;
break;
default:
throw new NotSupportedException("Unknown format: " + NonLinearStyle);
}
}
public void FromSerializeString(string s)
{
FromSerializeString(s, System.Globalization.CultureInfo.InvariantCulture);
}
public void FromTDCSerializeString()
{
_bIsValid = true;
}
/// <summary>
/// Will return a display string for a nonlinear calibration based on N4 formating
/// </summary>
public string ToDisplayString()
{
return ToDisplayString("N4");
}
/// <summary>
/// Will return a display string for a nonlinear calibration based on 1st paramater formating string
/// </summary>
/// <param name="nonlinearFormat"></param>
/// <returns></returns>
public string ToDisplayString(string nonlinearFormat)
{
if (string.IsNullOrEmpty(nonlinearFormat)) { nonlinearFormat = "N4"; }
switch (NonLinearStyle)
{
case NonLinearStyles.Polynomial:
{
return ToPolynomial(nonlinearFormat);
}
case NonLinearStyles.IRTraccZeroMMmV:
{
return $"mV = {MVAt0MM:n4}, {MMPerV:n4}*(V^{ToSuperScript(LinearizationExponent.ToString(nonlinearFormat))})";
}
case NonLinearStyles.IRTraccManual:
{
return $"((V^{ToSuperScript(LinearizationExponent.ToString(nonlinearFormat))})-{Intercept:n4})/{Slope:n4}";
}
case NonLinearStyles.IRTraccDiagnosticsZero:
{
return $"{MMPerV:n4}*(V^{ToSuperScript(LinearizationExponent.ToString(nonlinearFormat))})";
}
case NonLinearStyles.IRTraccAverageOverTime:
{
return $"{MMPerV:n4}*(V^{ToSuperScript(LinearizationExponent.ToString(nonlinearFormat))})";
}
case NonLinearStyles.IRTraccCalFactor:
{
return $"{ZeroPositionIntercept:n4}+{CalibrationFactor:n4}*(V^{ToSuperScript(LinearizationExponent.ToString(nonlinearFormat))})";
}
default:
return string.Empty;
}
}
private string ToPolynomial(string nonlinearFormat)
{
if (string.IsNullOrEmpty(nonlinearFormat)) { nonlinearFormat = "N4"; }
var sb = new StringBuilder();
var termNumber = PolynomialCoefficients.Length - 1;
foreach (var x in PolynomialCoefficients)
{
if (PolynomialCoefficients[termNumber] != 0)
{
var coeff = PolynomialCoefficients[termNumber];
// Let the appended math symbol handle sign unless we're the first term.
if (termNumber != PolynomialCoefficients.Length - 1)
{
coeff = Math.Abs(coeff);
}
sb.Append(coeff.ToString(nonlinearFormat));
if (PolynomialExponents[termNumber] != 0)
{
sb.Append("x");
if (PolynomialExponents[termNumber] != 1)
{
sb.Append(ToSuperScript(PolynomialExponents[termNumber].ToString("N0")));
}
}
if (termNumber > 0)
{
// Coerricients are Displayed in absolute value. We need to combine the sign with the addition symbol
sb.Append(PolynomialCoefficients[termNumber - 1] > 0 ? " + " : " - ");
}
}
termNumber--;
}
return sb.ToString();
}
private string ToSuperScript(string source)
{
var superScript = new StringBuilder();
foreach (var c in source)
{
switch (c)
{
case '-':
superScript.Append('\u207B');
break;
case '.':
superScript.Append('\u00B7');
break;
case '1':
superScript.Append('\u00B9');
break;
case '2':
superScript.Append('\u00B2');
break;
case '3':
superScript.Append('\u00B3');
break;
case '4':
superScript.Append('\u2074');
break;
case '5':
superScript.Append('\u2075');
break;
case '6':
superScript.Append('\u2076');
break;
case '7':
superScript.Append('\u2077');
break;
case '8':
superScript.Append('\u2078');
break;
case '9':
superScript.Append('\u2079');
break;
case '0':
superScript.Append('\u2070');
break;
case '\'':
superScript.Append('\u02C8');
break;
case ',':
superScript.Append('\u22C5'); // there is no unicode superscript comma. this comes close
break;
case '\u00A0':
superScript.Append('\u2009'); // unicode 'thin' space
break;
default:
superScript.Append('\u207F');
break;
}
}
return superScript.ToString();
}
/*
* we are given an equation in the form of y = ax^1 + b, except x and y are backwards for us (y=V where we'd prefer X was voltage, so we switch it)
* y/a - b/a = x, and then switch y and x, (1/a)x^1 -(b/a)x^0 = y
* now we want to get the coefficient of the first equation, which is "a", we get this by taking the inverse
* we get b on the other hand by taking -1 * (b/a)*a. if we have the "coefficient", we have a
*/
/*
public double GetIRTraccCoefficient()
{
foreach (Factor f in Factors)
{
if (f.Exponent == 1D) { return System.Math.Pow(f.Coefficient, -1); }
}
return 1D; //0 doesn't make sense for ir
}
public double GetIRTraccConstant()
{
foreach (Factor f in Factors)
{
if (f.Exponent == 0D) { return -1D * GetIRTraccCoefficient() * f.Coefficient; }
}
return 0D;
}
public void SetIRTraccFactor(double coefficient, double constant)
{
if (0 == coefficient)
{
//well this doesn't make any sense ...
coefficient = 1;
}
Factors = new Factor[]
{
new Factor(1/coefficient,1),
new Factor(-constant/coefficient,0),
};
}*/
}
}

View File

@@ -0,0 +1,62 @@
/*
Test.Module.Channel.Sensor.ExcitationVoltage.cs
Copyright © 2008
Diversified Technical Systems, Inc.
All Rights Reserved
*/
using System.ComponentModel;
namespace DTS.DAS.Concepts
{
// *** see Test.cs ***
public partial class Test
{
/// <summary>
/// A container for DTS generic module concepts.
/// </summary>
public sealed partial class Module
{
// *** see Test.Module.Channel.cs ***
public partial class Channel
{
//*** see Test.Module.Channel.Sensor.cs ***
public partial class Sensor
{
/// <summary>
/// All available Sensitivity Unit types.
/// </summary>
public enum SensUnits
{
/// <summary>
/// No Sensitivity Units (Polynomial Sensor)
/// </summary>
[Description("NONE")]
NONE = 0,
/// <summary>
/// Sensitivity expressed in mV with output at Capacity EU
/// </summary>
[Description("mV")]
mV = 1,
/// <summary>
/// Excitation proportional sensitivity expressed in mV/V with output at Capacity EU
/// </summary>
[Description("mV/V")]
mVperV = 2,
/// <summary>
/// Excitation proportional sensitivity expressed in mV/V/EU
/// </summary>
[Description("mV/V/EU")]
mVperVperEU = 3,
/// <summary>
/// Sensitivity expressed in mV/EU
/// </summary>
[Description("mV/EU")]
mVperEU = 4
}
}
}
}
}
}

View File

@@ -0,0 +1,42 @@
/*
Test.Module.Channel.Sensor.ShuntModeType.cs
Copyright © 2010
Diversified Technical Systems, Inc.
All Rights Reserved
*/
using System.ComponentModel;
namespace DTS.Common.DAS.Concepts
{
// *** see Test.cs ***
public partial class Test
{
/// <summary>
/// A container for DTS generic module concepts.
/// </summary>
public sealed partial class Module
{
// *** see Test.Module.Channel.cs ***
public partial class Channel
{
//*** see DTS.Common.DAS.Concepts.Test.Module.Channel.Sensor.cs ***
public partial class Sensor
{
public enum ShuntModeType
{
[Description("Internal")]
Internal,
[Description("External")]
External,
[Description("Emulation")]
Emulation,
[Description("None")]
None
}
}
}
}
}
}

View File

@@ -0,0 +1,171 @@
/*
* DAS.Id.cs
* DTM - why does this class exist? it's only encapsulating a string
* Copyright © 2009
* Diversified Technical Systems, Inc.
* All Rights Reserved
*/
using System;
using DTS.Common.Utilities;
namespace DTS.Common.DAS.Concepts.DAS
{
/// <summary>
/// Representation of the DTS.Common.DAS.Concepts.DAS.Id type.
/// why does this class even exist?
/// </summary>
public sealed class Id : Exceptional, IComparable<Id>, IEquatable<Id>
{
/// <summary>
/// The Thing In Itself.
/// </summary>
private readonly string value;
/// <summary>
/// Initialize an instance of the DTS.Common.DAS.Concepts.DAS.Id class.
/// </summary>
public Id(string value)
{
this.value = value;
}
/// <summary>
/// Allow DTS.Common.DAS.Concepts.DAS.Ids to be implicitly converted to strings.
/// </summary>
///
/// <param name="id">
/// The <see cref="Id"/> id to be stringified.
/// </param>
///
/// <returns>
/// The <see cref="string"/> value of this DTS.Common.DAS.Concepts.DAS.Id.
/// </returns>
///
public static implicit operator string(Id id)
{
return id.ToString();
}
/// <summary>
/// Allow strings to be implicitly converted to DTS.Slice.Control.DAS.Ids.
/// </summary>
///
/// <param name="id">
/// The <see cref="string"/> value to be DTS.Slice.Control.DAS.Id-ified.
/// </param>
///
/// <returns>
/// The <see cref="Id"/> equivalent to the specified string.
/// </returns>
///
public static implicit operator Id(string id)
{
return new Id(id);
}
public override bool Equals(object obj)
{
if (obj is Id that) { return Equals(that); }
return string.Compare(ToString(), obj.ToString(), StringComparison.OrdinalIgnoreCase) == 0;
}
/// <summary>
/// Determine whether this object instance and the specified object instance are equal.
/// </summary>
///
/// <param name="that">
/// The <see cref="Id"/> to be compared to this object instance.
/// </param>
///
/// <returns>
/// <see cref="bool"/> true if this object is equal to the specified object; false otherwise.
/// </returns>
///
public bool Equals(Id that)
{
if (value == that.value) { return true; }
if (null == value) { return false; }
if (null == that.value) { return false; }
return value.Equals(that.value, StringComparison.OrdinalIgnoreCase);
}
/// <summary>
/// Generate a comparison value between this object and another of it's type.
/// </summary>
///
/// <param name="that">
/// The <see cref="Id"/> to which this one is to be compared.
/// </param>
///
/// <returns>
/// An <see cref="int"/> value expressing the "similarity" between this object
/// and the one specified.
/// </returns>
///
public int CompareTo(Id that)
{
return Compare(this, that);
}
/// <summary>
/// Generate a string representation of this class.
/// </summary>
///
/// <returns>
/// The <see cref="string"/> representation of this object.
/// </returns>
///
public override string ToString()
{
return value;
}
/// <summary>
/// Generate a hash code for this instance.
/// </summary>
///
/// <returns>
/// The <see cref="int"/> hash code for this instance.
/// </returns>
///
public override int GetHashCode()
{
return value?.GetHashCode() ?? 0;
}
public static bool operator ==(Id left, Id right)
{
if (ReferenceEquals(left, null))
{
return ReferenceEquals(right, null);
}
return left.Equals(right);
}
public static int Compare(Id left, Id right)
{
if (left == right) { return 0; }
if (null == right) { return 1; }
if (null == left) { return -1; }
return string.Compare(left.ToString(), right.ToString(), StringComparison.OrdinalIgnoreCase);
}
public static bool operator >= (Id left, Id right)
{
return Compare(left, right) >= 0;
}
public static bool operator >(Id left, Id right)
{
return Compare(left, right) > 0;
}
public static bool operator <= (Id left, Id right)
{
return Compare(left, right) <= 0;
}
public static bool operator <(Id left, Id right)
{
return Compare(left, right) < 0;
}
public static bool operator !=(Id left, Id right)
{
return !(left == right);
}
}
}

View File

@@ -0,0 +1,230 @@
<?xml version="1.0" encoding="utf-8"?>
<ClassDiagram MajorVersion="1" MinorVersion="1">
<Class Name="DTS.Common.DAS.Concepts.DataScaler" Collapsed="true">
<Position X="11.75" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>yIIHsKRGAwEJpVQIBARAJBBuA1EgIBouDUBAUIBBABY=</HashCode>
<FileName>DataScaler.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.DAS.Concepts.DigitalInputScaleMultiplier" Collapsed="true">
<Position X="13.5" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAgAAIAAAgAAAAAAAAAhAAIAAAAQEAEEAAAA=</HashCode>
<FileName>DigitalInputScaleMultiplier.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.DAS.Concepts.RealtimeSample" Collapsed="true">
<Position X="11.75" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAgAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Interfaces\IRealtimeable.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.DAS.Concepts.LinearizationFormula" Collapsed="true">
<Position X="10" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>EBABiQDJAEEswAAoCAgAAQJCAYBXAKGgAABAAgKEMUA=</HashCode>
<FileName>LinearizationFormula.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.DAS.Concepts.Test" Collapsed="true">
<Position X="13.5" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>ShuntModeType.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.DAS.Concepts.TsrEvent" Collapsed="true" BaseTypeListCollapsed="true">
<Position X="8.25" Y="2.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAABCwAAAAAAAAAAAAAAAAAAEoAAAAAAAAAAAEABA=</HashCode>
<FileName>TsrEvent.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" Collapsed="true" />
</Class>
<Class Name="DTS.Common.DAS.Concepts.DAS.Channel&lt;TDataType&gt;" Collapsed="true">
<Position X="8.25" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>DAS\Channel\Channel.cs</FileName>
</TypeIdentifier>
</Class>
<Class Name="DTS.Common.DAS.Concepts.DAS.Id" Collapsed="true" BaseTypeListCollapsed="true">
<Position X="8.25" Y="1.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAQIAAAAAAAAAQEgAAAAAAAAAAAAKAAAAAAAAAAAAA=</HashCode>
<FileName>DAS\DAS.Id.cs</FileName>
</TypeIdentifier>
<Lollipop Position="0.2" Collapsed="true" />
</Class>
<Class Name="DTS.Common.DAS.Concepts.DAS.Channel.Data&lt;TDatumType&gt;" Collapsed="true">
<Position X="10" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>DAS\Channel\Data.cs</FileName>
</TypeIdentifier>
</Class>
<Interface Name="DTS.Common.DAS.Concepts.IArmable" Collapsed="true">
<Position X="0.5" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAEAAAAAAAAAAAgIAAAABAAAAAAAA=</HashCode>
<FileName>Interfaces\IArmable.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="DTS.Common.DAS.Concepts.ICalibratable" Collapsed="true">
<Position X="8.25" Y="3.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAQAAAAAAADAAAAAAAAAAIAAEAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Interfaces\ICalibratable.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="DTS.Common.DAS.Concepts.IDataCollectionEnabled" Collapsed="true">
<Position X="0.5" Y="1.75" Width="1.5" />
<TypeIdentifier>
<HashCode>BAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Interfaces\IDataCollectionEnabled.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="DTS.Common.DAS.Concepts.IDownloadEnabled" Collapsed="true">
<Position X="3.5" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAACAAAAABAQAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Interfaces\IDownloadEnabled.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="DTS.Common.DAS.Concepts.IGpioEnabled" Collapsed="true">
<Position X="8.25" Y="4.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABABAAAA=</HashCode>
<FileName>Interfaces\IGpioEnabled.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="DTS.Common.DAS.Concepts.IRealtimeable" Collapsed="true">
<Position X="11.75" Y="5.25" Width="1.5" />
<TypeIdentifier>
<HashCode>AIAAAQAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Interfaces\IRealtimeable.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="DTS.Common.DAS.Concepts.ITriggerable" Collapsed="true">
<Position X="5.75" Y="0.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Interfaces\ITriggerable.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="DTS.Common.DAS.Concepts.DAS.Channel.ICalSignalAware" Collapsed="true">
<Position X="10" Y="3.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAACAAAAAA=</HashCode>
<FileName>Interfaces\DAS\Channel\ICalSignalAware.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="DTS.Common.DAS.Concepts.DAS.Channel.IDecimatable&lt;T&gt;" Collapsed="true">
<Position X="11.75" Y="3.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAACAgAAAAAAAAAAAgAAAAAAAAAIAA=</HashCode>
<FileName>Interfaces\DAS\Channel\IDecimatable.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="DTS.Common.DAS.Concepts.DAS.Channel.IEngineeringUnitAware" Collapsed="true">
<Position X="13.5" Y="3.75" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Interfaces\DAS\Channel\IEngineeringUnitAware.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="DTS.Common.DAS.Concepts.DAS.Channel.IInversionAware" Collapsed="true">
<Position X="10" Y="4.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Interfaces\DAS\Channel\IInversionAware.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="DTS.Common.DAS.Concepts.DAS.Channel.IIsoCodeAware" Collapsed="true">
<Position X="11.75" Y="4.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAACAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Interfaces\DAS\Channel\IIsoCodeAware.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="DTS.Common.DAS.Concepts.DAS.Channel.ILevelTriggerable" Collapsed="true">
<Position X="8.25" Y="5.25" Width="1.5" />
<TypeIdentifier>
<HashCode>AAIAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAg=</HashCode>
<FileName>Interfaces\DAS\Channel\ILevelTriggerable.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="DTS.Common.DAS.Concepts.DAS.Channel.ILinearized" Collapsed="true">
<Position X="10" Y="5.25" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Interfaces\DAS\Channel\ILinearized.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="DTS.Common.DAS.Concepts.DAS.Channel.ISerialNumberAware" Collapsed="true">
<Position X="13.5" Y="5.25" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Interfaces\DAS\Channel\ISerialNumberAware.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="DTS.Common.DAS.Concepts.DAS.Channel.IShuntAware" Collapsed="true">
<Position X="8.25" Y="6" Width="1.5" />
<TypeIdentifier>
<HashCode>ABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAA=</HashCode>
<FileName>Interfaces\DAS\Channel\IShuntAware.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="DTS.Common.DAS.Concepts.DAS.Channel.IVoltageInsertionAware" Collapsed="true">
<Position X="10" Y="6" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAEAAAAAAAAAAAAAAAAAAAAAAgAAAAAAAAAAAAA=</HashCode>
<FileName>Interfaces\DAS\Channel\IVoltageInsertAware.cs</FileName>
</TypeIdentifier>
</Interface>
<Interface Name="DTS.Common.DAS.Concepts.DAS.Channel.ILargeDataAware" Collapsed="true">
<Position X="13.5" Y="4.5" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>Interfaces\ILargeDataAware.cs</FileName>
</TypeIdentifier>
</Interface>
<Enum Name="DTS.Common.DAS.Concepts.ArmStatus" Collapsed="true">
<Position X="8.25" Y="7" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAIBAAAAAAAAAAAAAAAIBAAAAAAAAgAAAAA=</HashCode>
<FileName>ArmStatus.cs</FileName>
</TypeIdentifier>
</Enum>
<Enum Name="DTS.Common.DAS.Concepts.AvailableArmModes" Collapsed="true">
<Position X="10" Y="7" Width="1.5" />
<TypeIdentifier>
<HashCode>AIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>AvailableArmModes.cs</FileName>
</TypeIdentifier>
</Enum>
<Enum Name="DTS.Common.DAS.Concepts.DAS.DecimationMethod" Collapsed="true">
<Position X="11.75" Y="7" Width="1.5" />
<TypeIdentifier>
<HashCode>ACAAAAAAAAAAhAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=</HashCode>
<FileName>DAS\DecimationMethod.cs</FileName>
</TypeIdentifier>
</Enum>
<Enum Name="DTS.Common.DAS.Concepts.DAS.Channel.LevelTriggerTypes" Collapsed="true">
<Position X="8.25" Y="7.75" Width="1.5" />
<TypeIdentifier>
<HashCode>ACAAAAACACAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAACA=</HashCode>
<FileName>DAS\Channel\LevelTriggerTypes.cs</FileName>
</TypeIdentifier>
</Enum>
<Enum Name="DTS.Common.Common.DAS.Concepts.GPIOPin.Directions" Collapsed="true">
<Position X="13.5" Y="7" Width="1.5" />
<TypeIdentifier>
<HashCode>AAAAAAAAAAAAAAAAAAAYAAAAEAQAAAAAAAAAgAAAAAA=</HashCode>
<FileName>Interfaces\IGpioEnabled.cs</FileName>
</TypeIdentifier>
</Enum>
<Font Name="Segoe UI" Size="9" />
</ClassDiagram>

View File

@@ -0,0 +1,54 @@
/*
Test.Module.RecordingMode.cs
Copyright © 2008
Diversified Technical Systems, Inc.
All Rights Reserved
*/
using DTS.Common.Enums.DASFactory;
using System;
using System.ComponentModel;
namespace DTS.Common.DAS.Concepts
{
// *** see Test.cs ***
public partial class Test
{
/// <summary>
/// A container for DTS generic module concepts.
/// </summary>
public sealed partial class Module
{
/// <summary>
/// Convert a string representation of a recording mode enumeration into its corresponding
/// enumeration value.
/// </summary>
///
/// <param name="recordingMode">
/// The <see cref="string"/> representation to be converted.
/// </param>
///
/// <returns>
/// The <see cref="Test.Module.RecordingMode"/> value corresponding to the
/// specified string, if any. If not, an exception will be thrown.
/// </returns>
///
public static DFConstantsAndEnums.RecordingMode GetRecordingModeFromString(string recordingMode)
{
try
{
return (DFConstantsAndEnums.RecordingMode)Enum.Parse(typeof(DFConstantsAndEnums.RecordingMode), recordingMode);
}
catch (Exception ex)
{
throw new Exception("encountered problem getting recording mode from string representation " + (null != recordingMode ? "\"" + recordingMode + "\"" : "<<NULL>>"), ex);
}
}
}
}
}

View File

@@ -0,0 +1,23 @@
namespace DTS.Common.DAS.Concepts.DAS
{
/// <summary>
/// Methods for determining the value of the representative point for decimated sets.
/// </summary>
public enum DecimationMethod
{
/// <summary>
/// Use that value of the PointsPerPoint-th point as the representative value.
/// </summary>
Point,
/// <summary>
/// Use the average of the PointsPerPoint values as the representative value.
/// </summary>
Average,
/// <summary>
/// Use the peak magnitude value of the PointsPerPoint values as the representative value.
/// </summary>
PeakMagnitude,
}
}

View File

@@ -0,0 +1,172 @@
/*
Test.Module.Channel.Sensor.ExcitationVoltage.cs
Copyright © 2008
Diversified Technical Systems, Inc.
All Rights Reserved
*/
using System;
using System.ComponentModel;
using DTS.Utilities;
namespace DTS.DAS.Concepts
{
// *** see Test.cs ***
public partial class Test
{
/// <summary>
/// A container for DTS generic module concepts.
/// </summary>
public sealed partial class Module
{
// *** see Test.Module.Channel.cs ***
public partial class Channel
{
//*** see Test.Module.Channel.Sensor.cs ***
public partial class Sensor
{
/// <summary>
/// All available excitation voltages.
/// </summary>
public enum ExcitationVoltageOption
{
/// <summary>
/// undefined excitation voltage
/// </summary>
[VoltageMagnitude(0.0)]
[Description("Undefined")]
Undefined=1,
/// <summary>
/// 2V
/// </summary>
[VoltageMagnitude(2.0)]
[Description("2.0")]
Volt2=2,
/// <summary>
/// 2.5V
/// </summary>
[VoltageMagnitude(2.5)]
[Description("2.5")]
Volt2_5=4,
/// <summary>
/// 3.0V
/// </summary>
[VoltageMagnitude(3.0)]
[Description("3.0")]
Volt3=8,
/// <summary>
/// 5V
/// </summary>
[VoltageMagnitude( 5.0 )]
[Description("5.0")]
Volt5=16,
/// <summary>
/// 10V
/// </summary>
[VoltageMagnitude( 10.0 )]
[Description("10.0")]
Volt10=32,
/// <summary>
/// 1V
/// </summary>
[VoltageMagnitude(1.0)]
[Description("1.0")]
Volt1 = 64
}
/// <summary>
/// Converts a specified excitation voltage option into its associated numeric value.
/// </summary>
///
/// <param name="target">
/// The <see cref="DTS.DAS.Concepts.Test.Module.Channel.Sensor.ExcitationVoltageOption"/> value
/// to be converted.
/// </param>
///
/// <returns>
/// The <see cref="double"/> magnitude associated with the specified voltage option.
/// </returns>
///
public static double GetExcitationVoltageMagnitudeFromEnum( ExcitationVoltageOption target )
{
try
{
return new VoltageMagnitudeAttributeCoder( ).DecodeAttributeValue( target );
}
catch ( Exception ex )
{
throw new Exception( "encountered problem attempting to get excitation voltage magnitude from enum", ex );
}
}
/// <summary>
/// Converts a specified voltage magnitude to the associated numeric value (if it exists;
/// otherwise an exception is thrown).
/// </summary>
///
/// <param name="magnitude">
/// The <see cref="double"/> magnitude to be converted.
/// </param>
///
/// <returns>
/// The <see cref="DTS.DAS.Concepts.Test.Module.Channel.Sensor.ExcitationVoltageOption"/> value
/// associated with the specified magnitude (if it exists).
/// </returns>
///
public static ExcitationVoltageOption GetExcitationVoltageEnumFromMagnitude( double magnitude )
{
try
{
return new VoltageMagnitudeAttributeCoder( ).EncodeAttributeValue( magnitude );
}
catch ( System.Exception ex )
{
throw new NotSupportedException( "encountered problem attempting to get excitation voltage enum from magnitude", ex );
}
}
/// <summary>
/// Attribute for specifying the numerical magnitude of the attached field's
/// "representation". Intended to be used with enumerations whose members represent
/// voltage magnitude options so that the enum item can have a corresponding numerical
/// value that can be extracted and used in calculations.
/// </summary>
[AttributeUsage(AttributeTargets.Field)]
public class VoltageMagnitudeAttribute: System.Attribute
{
private readonly double _Value;
/// <summary>
/// returns voltage magnitude
/// </summary>
public double Value { get { return _Value; } }
/// <summary>
/// constructs a <see cref="DTS.DAS.Concepts.Test.Module.Channel.Sensor.VoltageMagnitudeAttribute" />
/// with a given value
/// </summary>
/// <param name="value"></param>
public VoltageMagnitudeAttribute(double value) { _Value = value; }
}
/// <summary>
/// Object for manipulating voltage option enumeration-attached
/// <see cref="double"/> magnitude values.
/// </summary>
public class VoltageMagnitudeAttributeCoder
: AttributeCoder<ExcitationVoltageOption, VoltageMagnitudeAttribute, double>
{
/// <summary>
/// Initializes a <see cref="DTS.DAS.Concepts.Test.Module.Channel.Sensor.VoltageMagnitudeAttributeCoder"/> object.
/// </summary>
public VoltageMagnitudeAttributeCoder()
: base(attribute => attribute.Value, null)
{
}
}
}
}
}
}
}

View File

@@ -0,0 +1,33 @@
/*
* IGpioEnabled.cs
*
* Copyright © 2010
* Diversified Technical Systems, Inc.
* All Rights Reserved.
*/
using DTS.Common.Common.DAS.Concepts.GPIOPin;
namespace DTS.Common.Common.DAS.Concepts.GPIOPin
{
public enum Directions
{
Output = 0x00, Peripheral = 0x01, Input = 0x02,
InputPulledUp = 0x03, InputPulledDown = 0x04
};
}
namespace DTS.Common.DAS.Concepts
{ ///
/// <summary>
/// Representation of GPIO functionality.
/// </summary>
///
public interface IGpioEnabled
{
// TODO: Well have to bring these in as soon as we figure out where to get that enum from.
void SetGpio(uint Port, uint Pin, Directions Direction, bool State);
bool GetGpio(uint Port, uint Pin);
}
}

View File

@@ -0,0 +1,35 @@
/*
* DTS.Common.DAS.Concepts.DAS.Channel.IVoltageInsertionAware.cs
*
* Copyright © 2012
* Diversified Technical Systems, Inc.
* All Rights Reserved
*/
namespace DTS.Common.DAS.Concepts.DAS.Channel
{
/// <summary>
/// Definition of the concept of shunt-check awareness.
/// </summary>
public interface IVoltageInsertionAware
{
/// <summary>
/// Get/set this object's <see cref="double"/> measured shunt deflection value.
/// </summary>
double ExpectedGain
{
get;
set;
}
/// <summary>
/// Get/set this object's <see cref="double"/> target shunt deflection value.
/// </summary>
double MeasuredGain
{
get;
set;
}
}
}

View File

@@ -0,0 +1,25 @@
/*
* DTS.Common.DAS.Concepts.DAS.Channel.IIsoCodeAware.cs
*
* Copyright © 2009
* Diversified Technical Systems, Inc.
* All Rights Reserved
*/
namespace DTS.Common.DAS.Concepts.DAS.Channel
{
/// <summary>
/// Definition of the concept of ISO code awareness.
/// </summary>
public interface IIsoCodeAware
{
/// <summary>
/// Get/set this object's IsoCode <see cref="string"/>.
/// </summary>
string IsoCode
{
get;
set;
}
}
}

View File

@@ -0,0 +1,25 @@
/*
Test.Module.cs
Copyright © 2008
Diversified Technical Systems, Inc.
All Rights Reserved
*/
namespace DTS.DAS.Concepts
{
// *** see Test.cs ***
public partial class Test
{
/// <summary>
/// A container for DTS generic module concepts.
/// </summary>
public sealed partial class Module
{
/// <summary>
/// Class is not intended for instantiation.
/// </summary>
private Module( ) { }
}
}
}

View File

@@ -0,0 +1,34 @@
/*
* DAS.Channel.IInversionAware.cs
*
* Copyright © 2009
* Diversified Technical Systems, Inc.
* All Rights Reserved
*/
namespace DTS.DAS.Concepts.DAS.Channel
{
/// <summary>
/// Definition of the concept of inversion awareness.
/// </summary>
public interface IInversionAware
{ ///
/// <summary>
/// Get/set this object's inversion state <see cref="bool"/>.
/// </summary>
///
bool IsInverted
{
get;
set;
}
}
public interface ILinearized
{
LinearizationFormula LinearizationFormula
{
get;
set;
}
}
}

View File

@@ -0,0 +1,24 @@
/*
* DTS.Common.DAS.Concepts.DAS.Channel.cs
*
* Copyright © 2009
* Diversified Technical Systems, Inc.
* All Rights Reserved
*/
using DTS.Common.Utilities;
namespace DTS.Common.DAS.Concepts.DAS
{
/// <summary>
/// Slice control app's internal abstract representation of a DAS channel.
/// </summary>
///
/// <typeparam name="TDataType">
/// The "type" of the data contained by channels of this DAS.
/// </typeparam>
///
public abstract class Channel<TDataType> : Exceptional
{
}
}

View File

@@ -0,0 +1,175 @@
/*
Test.Module.Channel.Sensor.ExcitationVoltage.cs
Copyright © 2008
Diversified Technical Systems, Inc.
All Rights Reserved
*/
using System;
using System.ComponentModel;
using DTS.Common.Enums;
using DTS.Common.Utilities;
using DTS.Common.Utilities.Logging;
namespace DTS.Common.DAS.Concepts
{
// *** see Test.cs ***
public partial class Test
{
/// <summary>
/// A container for DTS generic module concepts.
/// </summary>
public sealed partial class Module
{
// *** see Test.Module.Channel.cs ***
public partial class Channel
{
//*** see DTS.Common.DAS.Concepts.Test.Module.Channel.Sensor.cs ***
public partial class Sensor
{
///// <summary>
///// All available excitation voltages.
///// </summary>
//public enum ExcitationVoltageOption
//{
// /// <summary>
// /// undefined excitation voltage
// /// </summary>
// [VoltageMagnitude(0.0)]
// [Description("Undefined")]
// Undefined=1,
// /// <summary>
// /// 2V
// /// </summary>
// [VoltageMagnitude(2.0)]
// [Description("2.0")]
// Volt2=2,
// /// <summary>
// /// 2.5V
// /// </summary>
// [VoltageMagnitude(2.5)]
// [Description("2.5")]
// Volt2_5=4,
// /// <summary>
// /// 3.0V
// /// </summary>
// [VoltageMagnitude(3.0)]
// [Description("3.0")]
// Volt3=8,
// /// <summary>
// /// 5V
// /// </summary>
// [VoltageMagnitude( 5.0 )]
// [Description("5.0")]
// Volt5=16,
// /// <summary>
// /// 10V
// /// </summary>
// [VoltageMagnitude( 10.0 )]
// [Description("10.0")]
// Volt10=32,
// /// <summary>
// /// 1V
// /// </summary>
// [VoltageMagnitude(1.0)]
// [Description("1.0")]
// Volt1 = 64
//}
/// <summary>
/// Converts a specified excitation voltage option into its associated numeric value.
/// </summary>
///
/// <param name="target">
/// The <see cref="ExcitationVoltageOptions.ExcitationVoltageOption"/> value
/// to be converted.
/// </param>
///
/// <returns>
/// The <see cref="double"/> magnitude associated with the specified voltage option.
/// </returns>
///
public static double GetExcitationVoltageMagnitudeFromEnum(ExcitationVoltageOptions.ExcitationVoltageOption target)
{
try
{
return new ExcitationVoltageOptions.VoltageMagnitudeAttributeCoder().DecodeAttributeValue(target);
}
catch (Exception ex)
{
throw new ArgumentException("encountered problem attempting to get excitation voltage magnitude from enum", ex);
}
}
/// <summary>
/// Converts a specified voltage magnitude to the associated numeric value (if it exists;
/// otherwise an exception is thrown).
/// </summary>
///
/// <param name="magnitude">
/// The <see cref="double"/> magnitude to be converted.
/// </param>
///
/// <returns>
/// The <see cref="ExcitationVoltageOptions.ExcitationVoltageOption"/> value
/// associated with the specified magnitude (if it exists).
/// </returns>
///
public static ExcitationVoltageOptions.ExcitationVoltageOption GetExcitationVoltageEnumFromMagnitude(double magnitude)
{
try
{
return new ExcitationVoltageOptions.VoltageMagnitudeAttributeCoder().EncodeAttributeValue(magnitude);
}
catch (Exception ex)
{
APILogger.Log("encountered problem attempting to get excitation voltage enum from magnitude", ex);
return ExcitationVoltageOptions.ExcitationVoltageOption.Undefined;
}
}
///// <summary>
///// Attribute for specifying the numerical magnitude of the attached field's
///// "representation". Intended to be used with enumerations whose members represent
///// voltage magnitude options so that the enum item can have a corresponding numerical
///// value that can be extracted and used in calculations.
///// </summary>
//[AttributeUsage(AttributeTargets.Field)]
//public class VoltageMagnitudeAttribute: Attribute
//{
// /// <summary>
// /// returns voltage magnitude
// /// </summary>
// public double Value { get; }
// /// <summary>
// /// constructs a <see cref="Test.Module.Channel.Sensor.VoltageMagnitudeAttribute" />
// /// with a given value
// /// </summary>
// /// <param name="value"></param>
// public VoltageMagnitudeAttribute(double value) { Value = value; }
//}
///// <summary>
///// Object for manipulating voltage option enumeration-attached
///// <see cref="double"/> magnitude values.
///// </summary>
//public class VoltageMagnitudeAttributeCoder
// : AttributeCoder<ExcitationVoltageOptions.ExcitationVoltageOption, VoltageMagnitudeAttribute, double>
//{
// /// <summary>
// /// Initializes a <see cref="Test.Module.Channel.Sensor.VoltageMagnitudeAttributeCoder"/> object.
// /// </summary>
// public VoltageMagnitudeAttributeCoder()
// : base(attribute => attribute.Value, null)
// {
// }
//}
}
}
}
}
}

View File

@@ -0,0 +1,31 @@
/*
Test.Module.Channel.cs
Copyright © 2008
Diversified Technical Systems, Inc.
All Rights Reserved
*/
namespace DTS.DAS.Concepts
{
// *** see Test.cs ***
public partial class Test
{
/// <summary>
/// A container for DTS generic module concepts.
/// </summary>
public sealed partial class Module
{
/// <summary>
/// A container for DTS generic channel concepts.
/// </summary>
public sealed partial class Channel
{
/// <summary>
/// Class is not intended for instantiation.
/// </summary>
private Channel( ) { }
}
}
}
}

View File

@@ -0,0 +1,24 @@
/*
* DAS.Channel.cs
*
* Copyright © 2009
* Diversified Technical Systems, Inc.
* All Rights Reserved
*/
using DTS.Utilities;
namespace DTS.DAS.Concepts.DAS
{
/// <summary>
/// Slice control app's internal abstract representation of a DAS channel.
/// </summary>
///
/// <typeparam name="DataType">
/// The "type" of the data contained by channels of this DAS.
/// </typeparam>
///
public abstract class Channel<DataType> : Exceptional
{
}
}

View File

@@ -0,0 +1,115 @@
/*
* IDownloadEnabled.cs
*
* Copyright © 2010
* Diversified Technical Systems, Inc.
* All Rights Reserved.
*/
using System;
using DTS.Utilities;
/// <DevelopmentNote Developer="Paul Hrissikopoulos">
/// It may make sense to refactor this namespace to be DTS.DAS.Concepts.Tsr and rename the TSR-specific
/// event to "Event" so that the fully qualified name of the class is "DTS.DAS.Concepts.Tsr.Event", but
/// then maybe keep the IDownloadEnabled and other generic interfaces outside of the "Tsr"-specific
/// namespace...? No, should probably stay with Event, since it has an "Event" type referenced in the
/// interface.
/// </DevelopmentNote>
namespace DTS.DAS.Concepts
{ ///
/// <summary>
/// Representation of data and metadata associated with a TSR event.
/// </summary>
///
public abstract class TsrEvent : Exceptional, ICloneable
{
/// <summary>
/// The 1-based <see cref="UInt64"/> identifier for this event.
/// </summary>
public virtual UInt64 EventId { get; protected set; }
/// <summary>
/// The <see cref="System.DateTime"/> containing the date and time of this event.
/// </summary>
public virtual DateTime TimeStamp { get; protected set; }
/// <summary>
/// The <see cref="string"/> serial number of the hardware that captured this event.
/// </summary>
public virtual string SerialNumber { get; protected set; }
/// <summary>
/// The <see cref="string"/> alternate serial number of the hardware that captured the event.
/// </summary>
public virtual string AlternateSerialNumber { get; protected set; }
/// <summary>
/// The <see cref="double"/> duration in seconds of this event.
/// </summary>
public virtual double DurationSeconds { get; protected set; }
/// <summary>
/// The <see cref="double"/> maximum sample rate for this event.
/// </summary>
public virtual double MaxSampleRate { get; protected set; } // note this is the "highest" sample rate
/// <summary>
/// The <see cref="float"/> temperature (in C).
/// </summary>
public virtual float TemperatureC { get; protected set; }
/// <summary>
/// The <see cref="double"/> number of pre-trigger seconds.
/// </summary>
public virtual double PreTriggerSeconds { get; protected set; }
///
/// <summary>
/// Generate a shallow copy of this object.
/// </summary>
/// <returns>A shallow copy of this <see cref="object"/>.</returns>
///
public abstract object Clone();
}
///
/// <summary>
/// Representation of the ability to download from this object.
/// </summary>
///
public interface IDownloadEnabled
{ //
// TODO: Determine whether or not these things should be in here. Maybe the implementing
// object should just ask for them in the constructor and keep them private? I don't think
// these are universally applicable to something "download enabled"... are they?
//
//public uint MaximumStoredEventSizeSeconds { get; }
//public ushort DownloadIncrementSamples { get; }
//public string[] ChannelDescription { get; }
//public int TimeOffsetMilliseconds { get; }
/// <summary>
/// A list of download <see cref="DTS.DAS.Concepts.TsrEvent"/>s available for download.
/// </summary>
TsrEvent[] EventList {get;}
///
/// <summary>
/// Get the event data for the specified sample.
/// </summary>
/// <param name="Event">The <see cref="DTS.DAS.Concepts.TsrEvent"/> to have it's data extracted.</param>
/// <param name="FirstSample">The <see cref="UInt64"/> index of the first sample to be downloaded.</param>
/// <param name="LastSample">The <see cref="UInt64"/> index of the last sample to be downloaded.</param>
/// <returns>An array of <see cref="double"/> data arrays for each channel.</returns>
///
double [][] GetEventData( TsrEvent Event, UInt64 FirstSample, UInt64 LastSample ); // Any reason to do data as an out parameter rather than a return value?
// Have a subclassed channel class that has a data array, just so that 2-d array isn't so ambiguous?
/// <summary>
/// Determine whether or not the data on this download-enabled entity has been downloaded.
/// </summary>
bool DataHasBeenDownloaded { get; }
}
}

View File

@@ -0,0 +1,52 @@
/*
* DAS.Channel.Data.cs
*
* Copyright © 2009
* Diversified Technical Systems, Inc.
* All Rights Reserved
*/
using System.Collections.Generic;
using DTS.Utilities;
namespace DTS.DAS.Concepts.DAS.Channel
{
/// <summary>
/// Representation of a list of channel data.
/// </summary>
public abstract class Data<DatumType> : ExceptionalList<DatumType>
{
/// <summary>
/// Initialize an instance of the DTS.DAS.Concepts.DAS.Channel.Data class.
/// </summary>
protected Data( )
{
}
/// <summary>
/// Initialize an instance of the DTS.DAS.Concepts.DAS.Channel.Data class.
/// </summary>
///
/// <param name="capacity">
/// The number of elements that the list can initially store.
/// </param>
///
protected Data( int capacity )
: base( capacity )
{
}
/// <summary>
/// Initialize an instance of the DTS.DAS.Concepts.DAS.Channel.Data class.
/// </summary>
///
/// <param name="collection">
/// The collection whose elements are copied to the new list.
/// </param>
///
protected Data( IEnumerable<DatumType> collection )
: base( collection )
{
}
}
}

View File

@@ -0,0 +1,52 @@
/*
* DTS.Common.DAS.Concepts.DAS.Channel.Data.cs
*
* Copyright © 2009
* Diversified Technical Systems, Inc.
* All Rights Reserved
*/
using System.Collections.Generic;
using DTS.Common.Utilities;
namespace DTS.Common.DAS.Concepts.DAS.Channel
{
/// <summary>
/// Representation of a list of channel data.
/// </summary>
public abstract class Data<TDatumType> : ExceptionalList<TDatumType>
{
/// <summary>
/// Initialize an instance of the DTS.Common.DAS.Concepts.DAS.Channel.Data class.
/// </summary>
protected Data()
{
}
/// <summary>
/// Initialize an instance of the DTS.Common.DAS.Concepts.DAS.Channel.Data class.
/// </summary>
///
/// <param name="capacity">
/// The number of elements that the list can initially store.
/// </param>
///
protected Data(int capacity)
: base(capacity)
{
}
/// <summary>
/// Initialize an instance of the DTS.Common.DAS.Concepts.DAS.Channel.Data class.
/// </summary>
///
/// <param name="collection">
/// The collection whose elements are copied to the new list.
/// </param>
///
protected Data(IEnumerable<TDatumType> collection)
: base(collection)
{
}
}
}

View File

@@ -0,0 +1,113 @@
/*
Test.Module.RecordingMode.cs
Copyright © 2008
Diversified Technical Systems, Inc.
All Rights Reserved
*/
using System;
using System.ComponentModel;
namespace DTS.DAS.Concepts
{
// *** see Test.cs ***
public partial class Test
{
/// <summary>
/// A container for DTS generic module concepts.
/// </summary>
public sealed partial class Module
{
/// <summary>
/// All available recording mode options.
/// </summary>
public enum RecordingMode
{
/// <summary>
/// invalid mode, this can't be used
/// </summary>
[Description("Invalid arm mode")]
InvalidArmMode = 0,
/// <summary>
/// circular buffer mode (constant recording, trigger)
/// </summary>
[Description("Circular buffer")]
CircularBuffer = 1,
/// <summary>
/// recorder mode (start, trigger)
/// </summary>
[Description("Recorder mode")]
RecorderMode = 2,
/// <summary>
/// contant recording, trigger, rearm after data collected
/// </summary>
[Description("Circular buffer Multiple-Events")]
AutoCircularBufferMode = 4,
/// <summary>
/// recorder mode (start, trigger) rearm after data collected
/// </summary>
[Description("Recorder mode Multiple-Events")]
AutoRecorderMode = 5,
/// <summary>
/// ???
/// </summary>
[Description("Immediate mode")]
ImmediateMode = 0x06,
/// <summary>
/// ???
/// </summary>
[Description("High Power mode")]
HighPowerRecorderMode = 0x07,
/// <summary>
/// ???
/// </summary>
[Description("Low Power mode")]
LowPowerRecorderMode = 0x08,
/// <summary>
/// ???
/// </summary>
[Description("Continuous mode")]
ContinuousRecorderMode = 0x09,
/// <summary>
/// ???
/// </summary>
[Description("Hybrid mode")]
HybridRecorderMode = 0x0A,
/// <summary>
/// ???
/// </summary>
[Description("Hybrid mode Multiple-Events")]
MultiHybridRecorderMode = 0x0B
}
/// <summary>
/// Convert a string representation of a recording mode enumeration into its corresponding
/// enumeration value.
/// </summary>
///
/// <param name="recordingMode">
/// The <see cref="string"/> representation to be converted.
/// </param>
///
/// <returns>
/// The <see cref="DTS.DAS.Concepts.Test.Module.RecordingMode"/> value corresponding to the
/// specified string, if any. If not, an exception will be thrown.
/// </returns>
///
public static RecordingMode GetRecordingModeFromString( string recordingMode )
{
try
{
return ( RecordingMode )Enum.Parse( typeof( RecordingMode ), recordingMode );
}
catch ( Exception ex )
{
throw new Exception( "encountered problem getting recording mode from string representation " + ( null != recordingMode ? "\"" + recordingMode + "\"" : "<<NULL>>" ), ex );
}
}
}
}
}

Some files were not shown because too many files have changed in this diff Show More