首页 > 解决方案 > 使用 Reflection 为网站创建可扩展图表

问题描述

我正在尝试实现一个网站,只需将 DLL 放入文件夹即可添加新图表。在撰写本文时,尚不清楚需要哪些图表,这提供了一种部署新图表的简单方法,而无需重新部署整个网站。我正在使用 Google Charts 来提供 Google 功能,并且将显示每个图表每种类型的图表都继承自以下接口 public enum ChartType { BAR, COLUMN, PIE, TABLE }

public class DataColumn 
{
    public String ColumnType { get; set; }
    public String ColumnValue { get; set; }

}

public interface IChart
{
    /// <summary>
    /// Dictionary of Columns, Each column is defined as a type and title
    /// </summary>
    List<DataColumn> Columns { get; set; }

    /// <summary>
    /// ChartType, What type of Chart; possible values BAR, COLUMN, PIE, TABLE
    /// </summary>
    ChartType ChartType { get;  }

    /// <summary>
    /// Data - data for the chart
    /// </summary>
    String Data { get;  }

    /// <summary>
    /// Name of the chart, must be unique used to identify each chart stub
    /// </summary>
    String Name { get; }

    /// <summary>
    /// Title - the title that will be displayed above the chart
    /// </summary>
    String Title { get;  }

    /// <summary>
    /// What position will the legend of there is one.
    /// </summary>
    String LegendPosition { get;  }

}

下面使用上面的接口

public class ReferralDownloadCount : IChart, IDisposable
{
    List<ChartDemo.DataColumn> columns = null;

    public ReferralDownloadCount()
    {

        columns = new List<ChartDemo.DataColumn>()
        {
            new ChartDemo.DataColumn() { ColumnType = "String" , ColumnValue = "Date" },
            new ChartDemo.DataColumn() { ColumnType = "Number" , ColumnValue = "Referral Count"}
        };

    }

    /// <summary>
    /// Returns the chart data
    /// </summary>
    public String Data 
    { 
        get 
        {
            String sql                      = String.Empty;
            String jsonResult               = String.Empty;
            DataSet ds                      = null;
            DataTable dt                    = null;
            List<ReferralCountData> results = null;
            JsonSerializer serializer       = null;

            try
            {
                sql = "Select * From[Portal].[ReferralCount] Where DATEDIFF(d, [Download Date], Convert(Date, GETDATE())) < 8 Order By[Download Date] Asc";
                ds  = DataToolbox.Execute(new SqlConnection(Properties.Settings.Default.DataConnection), sql, CommandType.Text);

                if (ds.Tables.Count > 0)
                {
                    dt      = ds.Tables[0];                      // we really are only expecting one table
                    results = new List<ReferralCountData>();

                    serializer = new JsonSerializer();
                    serializer.Converters.Add(new JavaScriptDateTimeConverter());

                    foreach ( DataRow dr in dt.Rows)
                    {
                        using (ReferralCountData rcd = new ReferralCountData()
                        {
                            Label = ((System.DateTime)dr.ItemArray[0]).ToString("dd/MM/yyyy"),
                            Value = Convert.ToInt32(dr["Referral Count"])
                        })
                        {
                            results.Add(rcd);
                        }
                    }

                    jsonResult = JsonConvert.SerializeObject(results);


                }
            }
            catch ( System.Exception ex)
            {
                throw ex;
            }
            finally
            {

            }

            return jsonResult;
        } 
    } 

    public List<ChartDemo.DataColumn> Columns {
        get
        {
            return columns; 
        }
        set
        {
            columns = value;
        } 
    }

    public ChartType ChartType => ChartType.COLUMN;

    public string Name => "REFERRALCOUNT";

    public string Title => "Referral Download Count"; 

    public string LegendPosition => "None"; 

    public void Dispose()
    {
        
    }
}

该站点遍历包含 DLL 的目录,并搜索任何类(例如上面的类)以创建图表 然后提取从 IChart 继承的类,因为 GetChartPlugins 检查每个 DLL

static List<IChart> GetChartPlugins(List<Assembly> assemblies)
{

    List<Type> availableTypes = new List<Type>();
    List<Type> alertList = null;

    try
    {

        foreach (Assembly currentAssembly in assemblies)
            availableTypes.AddRange(currentAssembly.GetTypes());


        alertList = availableTypes.FindAll(delegate (Type t)
        {
            List<Type> interfaceTypes = new List<Type>(t.GetInterfaces());

            return interfaceTypes.Contains(typeof(IChart));
        });

    }
    catch (ReflectionTypeLoadException ex)
    {
        StringBuilder sb = new StringBuilder();
        foreach (Exception exSub in ex.LoaderExceptions)
        {
            sb.AppendLine(exSub.Message);
            FileNotFoundException exFileNotFound = exSub as FileNotFoundException;
            if (exFileNotFound != null)
            {
                if (!string.IsNullOrEmpty(exFileNotFound.FusionLog))
                {
                    sb.AppendLine("Fusion Log:");
                    sb.AppendLine(exFileNotFound.FusionLog);
                }
            }
            sb.AppendLine();
        }
        string errorMessage = sb.ToString();
    }
    catch ( System.Exception ex)
    {
        throw ex;
    }
    finally
    {

    }

    // convert the list of Objects to an instantiated list of ICalculators
    return alertList.ConvertAll<IChart>(delegate (Type t) { return Activator.CreateInstance(t) as IChart; });
}

但是,当它运行时,尝试调用 currentAssembly.GetTypes() 时会抛出一个 ReflectionTypeLoadException 最终变成;

来自程序集“ReferralManagementCharts,Version=1.0.0.0,Culture=neutral,PublicKeyToken=null”的“ReferralManagementCharts.ReferralDownloadCount”类型中的方法“get_Columns”没有实现。任何人都可以看到为什么因为 ReferralDownlodCount 的 Columns 属性

    public List<ChartDemo.DataColumn> Columns {
        get
        {
            return columns; 
        }
        set
        {
            columns = value;
        } 
    }

有得到。

标签: c#reflectioninterface

解决方案


推荐阅读