-2

I have the following interface

public interface IQueryBuilder
{
    SqlCommand Build(IReportDataSource dataSource, List<IReportColumn> columns, List<IReportRelationMapping> relationMappings, IReportFilterMapping filters, List<IReportColumn> columsToSortBy, ReportFormat reportFormat);

    string GetSqlClause(List<IReportFilter> reportFilters, ref List<IDataParameter> sqlParams);
}

However, I would like to be able to access the method GetSqlClause in the implementation directly.

Here is how I implemented the above

public class QueryBuilder : IQueryBuilder
{
    public SqlCommand Build(IReportDataSource dataSource, List<IReportColumn> columns, List<IReportRelationMapping> relationMappings, IReportFilterMapping filters, List<IReportColumn> columsToSortBy, ReportFormat reportType)
    {
        //Do something awsome!!!
        string sqlQuery = "";

        List<IDataParameter> sqlParameters = new List<IDataParameter>();

        return this.GetSqlCommand(sqlQuery, sqlParameters);
    }

    private SqlCommand GetSqlCommand(string sqlQuery, List<IDataParameter> sqlParams)
    {
        var command = new SqlCommand(sqlQuery);

        foreach (IDataParameter dataParameter in sqlParams)
        {
            command.Parameters.Add(dataParameter);
        }

        return command;
    }


    public static string GetSqlClause(List<IReportFilter> reportFilters, ref List<IDataParameter> sqlParams)
    {
        string sqlFilter = "";

        if (reportFilters != null && reportFilters.Any())
        {
            //At this point we know there are some filter to add to the list

            var firstFilter = reportFilters.First();

            foreach (var reportFilter in reportFilters)
            {

                var parameter = GenerateDbParameter("p" + sqlParams.Count, reportFilter.FormattedValue, SqlDbType.NVarChar);
                ....
                ....
            }
        }

        return sqlFilter;
    }

    private static IDataParameter GenerateDbParameter(string parameterName, object parameterValue, SqlDbType parameterType)
    {
        if (string.IsNullOrEmpty(parameterName) || parameterValue == null)
        {
            throw new ArgumentException();
        }
        var parameter = new SqlParameter("@" + parameterName, parameterType)
        {
            Value = parameterValue
        };

        return parameter;
    }


}

Because I am using static on my GetSqlClause method I get an error

cannot implement an interface member because it is static.

What is a good work around to this problem? How can I access my GetSqlClause directly?

Jaylen
  • 39,043
  • 40
  • 128
  • 221

2 Answers2

0

If you want your method to be static and implement an interface, the language won't let you do that, but you can work around it in several ways:

  • If accessing the whole implementation from a static context makes sense, you can simply declare a singleton object:

    public static QueryBuilder Instance { get; } = new QueryBuilder();
    

    And now you have access to the QueryBuilder.Instance static property, whose value implements IQueryBuilder.

  • Through an explicit method implementation. This is an additional instance method which implements the interface method, and whose signature won't conflict with another method in the class.

    string IQueryBuilder.GetSqlClause(List<IReportFilter> reportFilters, ref List<IDataParameter> sqlParams)
    {
        // Call the static method, this is *not* a recursive call
        return GetSqlClause(reportFilters, ref sqlParams);
    }
    

    The general syntax of an explicit implementation is:

    ReturnType InterfaceName.MethodName(ParamType param)
    {
        ...
    }
    
  • Another (simpler) solution would be to use two distinct method names.

Lucas Trzesniewski
  • 50,214
  • 11
  • 107
  • 158
-1

C# doesn't support static members implementing interface methods.

Daniel A. Thompson
  • 1,904
  • 1
  • 17
  • 26