public abstract bool TryGetData(DataRequest dataRequest, DataCollectionContext context, out object result);
        void Initialize()
        {
            DataRequestCache.Clear();

            var lines = Pattern.GetLines(keepLineBreaks: false);
            var trimmedPattern = string.Concat(lines.Select(l => l.Trim()));

            Template = Template.FromText(trimmedPattern);

            var placeholders = Template.GetPlaceholders();

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

                if (!ph.SubstitutionPattern.StartsWith("'") && !ph.SubstitutionPattern.EndsWith("'"))
                {
                    var dr = new DataRequest();
                    dr.Data = ph.SubstitutionPattern;
                    DataRequestCache.Add(dr);

                    var cph = ph as ConditionalPlaceholder;
                    if (cph != null)
                    {

                        if (!cph.TrueOutcomeSubstitutionPattern.StartsWith("'") && !cph.TrueOutcomeSubstitutionPattern.EndsWith("'"))
                        {
                            dr = new DataRequest();
                            dr.Data = cph.TrueOutcomeSubstitutionPattern;
                            DataRequestCache.Add(dr);
                        }
                    }
                }
            }
        }
        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;
        }