CollectData(IList<DataRequest> requestedContextData)
        {
            var result = new List<DiagnosticEventProperty>(capacity: requestedContextData.Count);

            if (requestedContextData.Count == 0)
                return result;

            var cx = new DataCollectionContext();

            for (int i = 0; i < requestedContextData.Count; i++)
            {
                var item = requestedContextData[i];

                DiagnosticEventProperty property = null;

                //# try to get from cache first
                if (DataRequestCache.TryGetValue(item, out property))
                {
                    result.Add(property);
                    continue;
                }

                //# get the data
                var dataValue = (object)null;

                if (TryGetData(item, cx, out dataValue))
                {
                    property = new DiagnosticEventProperty();
                    property.UniqueName = item.Data;
                    property.Value = dataValue;
                }

                result.AddIfNotNull(property);

                // add to cache if needed
                if (item.IsCached && !DataRequestCache.ContainsKey(item))
                    DataRequestCache.Add(item, property);
            }

            return result;
        }
 public abstract bool TryGetData(DataRequest dataRequest, DataCollectionContext context, out object result);
        public override bool TryGetData(DataRequest request, DataCollectionContext cx, out object result)
        {
            try
            {
                result = null;

                if(request.Data == "Application.Version")
                {
                    if(ApplicationIsNetworkDeployed)
                    {
                        result = ApplicationDeployment.CurrentDeployment.CurrentVersion;
                        return true;
                    }

                    var entryAssembly = Assembly.GetEntryAssembly();

                    if(entryAssembly != null)
                    {
                        result = entryAssembly.GetName().Version;
                        return true;
                    }
                }

                //# Current Thread
                if (request.Data == "Thread.Id")
                {
                    result = cx.CurrentThread.ManagedThreadId;
                    return true;
                }

                if (request.Data == "Thread.Name")
                {
                    result = cx.CurrentThread.Name;
                    return true;
                }

                if (request.Data == "Thread.ThreadState")
                {
                    result = cx.CurrentThread.ThreadState;
                    return true;
                }

                if (request.Data == "Thread.IsBackground")
                {
                    result = cx.CurrentThread.IsBackground;
                    return true;
                }

                if (request.Data == "Thread.UICulture")
                {
                    result = CultureInfo.CurrentUICulture.EnglishName;
                    return true;
                }

                if (request.Data == "Thread.Culture")
                {
                    result = CultureInfo.CurrentCulture.EnglishName;
                    return true;
                }

                //# Time

                if (request.Data == "DateTime.Utc")
                {
                    result = DateTime.UtcNow;
                    return true;
                }

                if (request.Data == "DateTime.Local")
                {
                    result = DateTime.Now;
                    return true;
                }

                //# Environment
                if (request.Data == "Environment.CommandLineArgs")
                {
                    result = string.Join(
                            " ",
                            Environment.GetCommandLineArgs()
                            .Select(s =>
                            {
                                if (s.Contains(" "))
                                    return string.Format("\"{0}\"", s);
                                else return s;
                            }));

                    return true;
                }

                if (request.Data == "Environment.Version")
                {
                    result = Environment.Version;
                    return true;
                }

                if (request.Data == "Environment.HasShutdownStarted")
                {
                    result = Environment.HasShutdownStarted;
                    return true;
                }

                if (request.Data == "Environment.OSVersion")
                {
                    result = Environment.OSVersion;
                    return true;
                }

                if (request.Data == "Environment.OSVersion.Platform")
                {
                    result = Environment.OSVersion.Platform;
                    return true;
                }

                if (request.Data == "Environment.OSVersion.ServicePack")
                {
                    result = Environment.OSVersion.ServicePack;
                    return true;
                }

                if (request.Data == "Environment.OSVersion.Version")
                {
                    result = Environment.OSVersion.Version;
                    return true;
                }

                if (request.Data == "Environment.CurrentDirectory")
                {
                    result = Environment.CurrentDirectory;
                    return true;
                }

                if (request.Data == "Environment.SystemDirectory")
                {
                    result = Environment.SystemDirectory;
                    return true;
                }

                if (request.Data == "Environment.Is64BitOperatingSystem")
                {
                    result = Environment.Is64BitOperatingSystem;
                    return true;
                }

                if (request.Data == "Environment.Is64BitProcess")
                {
                    result = Environment.Is64BitProcess;
                    return true;
                }

                if (request.Data == "Environment.MachineName")
                {
                    result = Environment.MachineName;
                    return true;
                }

                if (request.Data == "Environment.ProcessorCount")
                {
                    result = Environment.ProcessorCount;
                    return true;
                }

                if (request.Data == "Environment.SystemPageSizeMB")
                {
                    result = Environment.SystemPageSize.ToMegaBytes();
                    return true;
                }

                if (request.Data == "Environment.SystemPageSizeMiB")
                {
                    result = Environment.SystemPageSize.ToMebiBytes();
                    return true;
                }

                if (request.Data == "Environment.UserDomainName")
                {
                    result = Environment.UserDomainName;
                    return true;
                }

                if (request.Data == "Environment.UserName")
                {
                    result = Environment.UserName;
                    return true;
                }

                if (request.Data == "Environment.UserInteractive")
                {
                    result = Environment.UserInteractive;
                    return true;
                }

                if (request.Data == "Network.IsNetworkAvailable")
                {
                    result = NetworkInterface.GetIsNetworkAvailable();
                    return true;
                }

                //# Current Process
                if (request.Data == "Process.PagedMemorySize (MB)")
                {
                    result = cx.CurrentProcess.PagedMemorySize64.ToMegaBytes();
                    return true;
                }

                if (request.Data == "Process.MaxWorkingSet (MB)")
                {
                    result = cx.CurrentProcess.MaxWorkingSet.ToInt64().ToMegaBytes();
                    return true;
                }

                if (request.Data == "Process.NonpagedSystemMemorySize (MB)")
                {
                    result = cx.CurrentProcess.NonpagedSystemMemorySize64.ToMegaBytes();
                    return true;
                }

                if (request.Data == "Process.PagedSystemMemorySize (MB)")
                {
                    result = cx.CurrentProcess.PagedSystemMemorySize64.ToMegaBytes();
                    return true;
                }

                if (request.Data == "Process.PrivateMemorySize (MB)")
                {
                    result = cx.CurrentProcess.PrivateMemorySize64.ToMegaBytes();
                    return true;
                }

                if (request.Data == "Process.VirtualMemorySize (MB)")
                {
                    result = cx.CurrentProcess.VirtualMemorySize64.ToMegaBytes();
                    return true;
                }

                if (request.Data == "Process.WorkingSet (MB)")
                {
                    result = cx.CurrentProcess.WorkingSet64.ToMegaBytes();
                    return true;
                }

                if (request.Data == "Process.PagedMemorySize (MiB)")
                {
                    result = cx.CurrentProcess.PagedMemorySize64.ToMebiBytes();
                    return true;
                }

                if (request.Data == "Process.PagedMemorySize (MB)")
                {
                    result = cx.CurrentProcess.PagedMemorySize64.ToMegaBytes();
                    return true;
                }

                if (request.Data == "Process.MaxWorkingSet (MiB)")
                {
                    result = cx.CurrentProcess.MaxWorkingSet.ToInt64().ToMebiBytes();
                    return true;
                }

                if (request.Data == "Process.MaxWorkingSet (MB)")
                {
                    result = cx.CurrentProcess.MaxWorkingSet.ToInt64().ToMegaBytes();
                    return true;
                }

                if (request.Data == "Process.NonpagedSystemMemorySize (MiB)")
                {
                    result = cx.CurrentProcess.NonpagedSystemMemorySize64.ToMebiBytes();
                    return true;
                }

                if (request.Data == "Process.NonpagedSystemMemorySize (MB)")
                {
                    result = cx.CurrentProcess.NonpagedSystemMemorySize64.ToMegaBytes();
                    return true;
                }

                if (request.Data == "Process.PagedSystemMemorySize (MiB)")
                {
                    result = cx.CurrentProcess.PagedSystemMemorySize64.ToMebiBytes();
                    return true;
                }

                if (request.Data == "Process.PagedSystemMemorySize (MB)")
                {
                    result = cx.CurrentProcess.PagedSystemMemorySize64.ToMegaBytes();
                    return true;
                }

                if (request.Data == "Process.PrivateMemorySize (MiB)")
                {
                    result = cx.CurrentProcess.PrivateMemorySize64.ToMebiBytes();
                    return true;
                }

                if (request.Data == "Process.PrivateMemorySize (MB)")
                {
                    result = cx.CurrentProcess.PrivateMemorySize64.ToMegaBytes();
                    return true;
                }

                if (request.Data == "Process.VirtualMemorySize (MiB)")
                {
                    result = cx.CurrentProcess.VirtualMemorySize64.ToMebiBytes();
                    return true;
                }

                if (request.Data == "Process.VirtualMemorySize (MB)")
                {
                    result = cx.CurrentProcess.VirtualMemorySize64.ToMegaBytes();
                    return true;
                }

                if (request.Data == "Process.WorkingSet (MiB)")
                {
                    result = cx.CurrentProcess.WorkingSet64.ToMebiBytes();
                    return true;
                }

                if (request.Data == "MemoryStatus.MemoryLoad")
                {
                    if (!this.MemoryStatus.IsOSSupported)
                        return false;

                    this.MemoryStatus.Refresh(TimeSpan.FromSeconds(1));

                    result = MemoryStatus.MemoryLoad;
                    return true;
                }

                if (request.Data == "MemoryStatus.AvailablePageFile (MB)")
                {
                    if (!this.MemoryStatus.IsOSSupported)
                        return false;

                    this.MemoryStatus.Refresh(TimeSpan.FromSeconds(1));

                    result = MemoryStatus.AvailablePageFile.ToMegaBytes();
                    return true;
                }

                if (request.Data == "MemoryStatus.AvailablePhysical (MB)")
                {
                    if (!this.MemoryStatus.IsOSSupported)
                        return false;

                    this.MemoryStatus.Refresh(TimeSpan.FromSeconds(1));

                    result = MemoryStatus.AvailablePhysical.ToMegaBytes();
                    return true;
                }

                if (request.Data == "MemoryStatus.AvailableVirtual (MB)")
                {
                    if (!this.MemoryStatus.IsOSSupported)
                        return false;

                    this.MemoryStatus.Refresh(TimeSpan.FromSeconds(1));

                    result = MemoryStatus.AvailableVirtual.ToMegaBytes();
                    return true;
                }

                if (request.Data == "MemoryStatus.TotalPageFile (MB)")
                {
                    if (!this.MemoryStatus.IsOSSupported)
                        return false;

                    this.MemoryStatus.Refresh(TimeSpan.FromSeconds(1));

                    result = MemoryStatus.TotalPageFile.ToMegaBytes();
                    return true;
                }

                if (request.Data == "MemoryStatus.TotalPhysical (MB)")
                {
                    if (!this.MemoryStatus.IsOSSupported)
                        return false;

                    this.MemoryStatus.Refresh(TimeSpan.FromSeconds(1));

                    result = MemoryStatus.TotalPhysical.ToMegaBytes();
                    return true;
                }

                if (request.Data == "MemoryStatus.TotalVirtual (MB)")
                {
                    if (!this.MemoryStatus.IsOSSupported)
                        return false;

                    this.MemoryStatus.Refresh(TimeSpan.FromSeconds(1));

                    result = MemoryStatus.TotalVirtual.ToMegaBytes(); ;
                    return true;
                }

                if (request.Data == "Process.UpTime")
                {
                    result = ((TimeSpan)(DateTime.Now - cx.CurrentProcess.StartTime)).ToString();
                    return true;
                }

                if (request.Data == "Deployment.IsNetworkDeployed")
                {
                    result = ApplicationIsNetworkDeployed;
                    return true;
                }

                if (request.Data == "Deployment.ActivationUri")
                {
                    if (!ApplicationIsNetworkDeployed)
                        return false;

                    result = ApplicationDeployment.CurrentDeployment.ActivationUri;
                    return true;
                }

                if (request.Data == "Deployment.CurrentVersion")
                {
                    if (!ApplicationIsNetworkDeployed)
                        return false;

                    result = ApplicationDeployment.CurrentDeployment.CurrentVersion;
                    return true;
                }

                if (request.Data == "Deployment.DataDirectory")
                {
                    if (!ApplicationIsNetworkDeployed)
                        return false;

                    result = ApplicationDeployment.CurrentDeployment.DataDirectory;
                    return true;
                }

                if (request.Data == "Deployment.IsFirstRun")
                {
                    if (!ApplicationIsNetworkDeployed)
                        return false;

                    result = ApplicationDeployment.CurrentDeployment.IsFirstRun;
                    return true;
                }

                if (request.Data == "Deployment.TimeOfLastUpdateCheck")
                {
                    if (!ApplicationIsNetworkDeployed)
                        return false;

                    result = ApplicationDeployment.CurrentDeployment.TimeOfLastUpdateCheck;
                    return true;
                }

                if (request.Data == "Deployment.UpdatedApplicationFullName")
                {
                    if (!ApplicationIsNetworkDeployed)
                        return false;

                    result = ApplicationDeployment.CurrentDeployment.UpdatedApplicationFullName;
                    return true;
                }

                if (request.Data == "Deployment.UpdatedVersion")
                {
                    if (!ApplicationIsNetworkDeployed)
                        return false;

                    result = ApplicationDeployment.CurrentDeployment.UpdatedVersion;
                    return true;
                }

                if (request.Data == "Deployment.UpdateLocation")
                {
                    if (!ApplicationIsNetworkDeployed)
                        return false;

                    result = ApplicationDeployment.CurrentDeployment.UpdateLocation;
                    return true;
                }

                if (request.Data == "System.Processes (Top 10 by Memory)")
                {
                    result =
                        (from p in Process.GetProcesses()
                         orderby p.WorkingSet64 descending
                         select new { Name = p.ProcessName, WorkingSetMB = p.WorkingSet64.ToMegaBytes() })
                         .Take(10)
                         .ToList();

                    return true;
                }

                // TODO:
                //result.TryAddProperty("Process.IsElevated", () => shell32.IsUserAnAdmin());
                //result.TryAddProperty("Process.IntegrityLevel", () => advapi32.GetProcessIntegrityLevel());

            }
            catch(Exception ex)
            {

                // TODO: log warning
            }

            result = null;
            return false;
        }