Amzath
Amzath

Reputation: 3249

Is it possible using C# generic

Here is the interface I need to define. I could not because generic type parameter in Parameters property does not exist. Is there a way to achieve this kind of interface definition in C#?

UPDATED I did not want to define interface like this: ICriteria<T>.

public interface ICriteria
{
    string Text { get; set; }
    IList<IParameter<T>> Parameters { get; set; }
}

UPDATED

As more detail required why I would not want go that route. Here is more information about it. I have Parameter interface and implementaion like this

public interface IParameter<T>
{
    string Name { get; set; }
    T Value { get; set; }
}

public class Parameter<T> : IParameter<T>
{
    public string Name { get; set; }
    public T Value { get; set; }
}

And the method consumes above implementation like this

public ICriteria BuildQuery()
    {
        ICriteria criteria = new Criteria();
        criteria.Text = "dbo.Messages";

        var chatRoom = new Parameter<int>() { Name = "ChatRoomId", Value = _chatRoomId };
        var startDate = new Parameter<DateTime>() { Name = "StartDate", Value = _startDateTime };
        var endDate = new Parameter<DateTime>() { Name = "EndDate", Value = _endDateTime };

        //I want to add all parameters to criteria instance
        criteria.Parameters.Add(chatRoom);
        criteria.Parameters.Add(startDate);
        criteria.Parameters.Add(endDate);

        return criteria;
    }

The above method creates different type of parameters and try to add them to Parameters list in ICriteria interface. Hope it make sense.

Upvotes: 1

Views: 163

Answers (3)

OZnew
OZnew

Reputation: 58

Maybe you can add constraint for your generic type:

   public interface ICriteria<T,S>
        where T : IParameter<S>
    {
        string Text { get; set; }
        IList<T> Parameters { get; set; }
    }

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1500525

As mentioned, you can't do that. But what you could do is this:

public interface IParameter
{
    // Any members which don't need T
}

public interface IParameter<T> : IParameter
{
    // Any members which do need to refer to T
}

public interface ICriteria
{
    string Text { get; set; }
    IEnumerable<IParameter> WeakParameters { get; }
}

public interface ICriteria<T> : ICriteria
{
    IList<IParameter<T>> StrongParameters { get; }
}

A typical implementation would make the WeakParameters call just return StrongParameters (assuming you're using C# 4 with generic covariance). Another option would be to make the strong form hide the weak form:

// Parameter types as before

public interface ICriteria
{
    string Text { get; set; }
    IEnumerable<IParameter> Parameters { get; }
}

public interface ICriteria<T> : ICriteria
{
    new IList<IParameter<T>> Parameters { get; }
}

Then anything which only had a reference of compile-time type ICriteria would get the "weak" sequence, whereas anything with a reference of compile-time type ICriteria<T> would get the "strong" list.

EDIT: This is all assuming that you want a single T for all parameters on a single ICriteria instance. If that's not the case, then you might want:

// Parameter types as before

public interface ICriteria
{
    string Text { get; set; }
    IList<IParameter> Parameters { get; }
}

You can add any kind of IParameter<T> to it, varying the T with each call, but when you're reading the parameters you don't have the information (at compile-time) about which parameter has which type (or indeed whether the parameter even implements the strongly-typed interface).

Upvotes: 3

Paul Bellora
Paul Bellora

Reputation: 55213

You would need to declare a type parameter T for your ICriteria interface in order to use it in its body:

public interface ICriteria<T>
{
   string Text { get; set; }
   IList<IParameter<T>> Parameters { get; set; }
}

I think this is what your intention is; please let me know if I misunderstood the question.

Upvotes: 4

Related Questions