Sean Anderson
Sean Anderson

Reputation: 29301

Getter and Setter in generic interface - is this possible?

Still learning my ways around C# generics... is it possible to achieve this functionality?

public interface ISetting<T>
{
    void SetSettings(T obj);
    // myTypeHere GetSettings(T obj);
}

public class RadDockSetting : ISetting<CormantRadDock>
{
    public RadDockSetting()
    {
    }

    public RadDockSetting GetSettings(CormantRadDock dock)
    {
    }

    public void SetSettings(CormantRadDock dock)
    {
    }
 }

I realize this is a counter-intuitive way to be using a Getter -- shouldn't have to pass anything to it. What I'm doing is creating an object, RadDockSetting, that stores the relevant properties of the CormantRadDock -- and then returns the 'got' settings.

GetSettings is currently a static method, but I realize this will need to be refactored in order to allow implementing a getter from the interface. Maybe once this occurs the 'weirdness' of the getter will fall away?

So, a little background on all of this:

I started with a class that had a lot of 'copy/pasted' functions. These functions were in charge of saving and removing controls from a manager. When I realized this I set out trying to make these functions more generic. I succeeded, with SO's help, in making remove generic.

For reference, here is remove:

public static void Remove<T>(string controlID) where T: new()
{
    Logger.InfoFormat("Removing control {0}", controlID);
    T states = RadControlStates.GetStates<T>();
    (states as IDictionary).Remove(controlID);
    RadControlStates.SetStates<T>(states);
}

and it is called like so: RadControlSave.Remove<SerializableDictionary<string, RadPaneSetting>>(ID);

Now, I am trying to extend this genericness to the rest of the methods -- the savers. Here's how one of these methods looks currently:

public static void SavePane(CormantRadPane pane)
{
    Logger.InfoFormat("Saving pane {0}", pane.ID);
    RadPaneSetting paneSettings = RadPaneSetting.GetSettings(pane);
    SerializableDictionary<string, RadPaneSetting> paneStates = RadControlStates.GetStates<SerializableDictionary<string, RadPaneSetting>>();

    bool paneIsKnown = paneStates.ContainsKey(paneSettings.ID);

    if (paneIsKnown)
    {
        Logger.Debug("Pane is known. Overwriting data.");
        paneStates[paneSettings.ID] = paneSettings;
    }
    else
    {
        Logger.Debug("Pane is unknown. Saving data.");
        paneStates.Add(paneSettings.ID, paneSettings);
    }

    RadControlStates.SetStates<SerializableDictionary<string, RadPaneSetting>>(paneStates);
}

At the start of this code block there is a call to "RadPaneSetting.GetSettings(pane)".

RadPaneSettings implements the ISettings interface. Here is ISetting's setter being used.

/// <summary>
/// Recreates a dashboard control based off of its settings.
/// </summary>
/// <typeparam name="T"> The type of control to be recreated. </typeparam>
/// <param name="settings"> The known settings needed to recreate the control.</param>
/// <returns> The recreated control. </returns>
public static T Recreate<T>(ISetting<T> settings) where T : new()
{
    T _control = new T();
    settings.SetSettings(_control);
    Logger.DebugFormat("Recreated control {0}", (_control as Control).ID);
    return _control;
}

Upvotes: 0

Views: 4852

Answers (5)

ckramer
ckramer

Reputation: 9443

What you have would work if you define another generic parameter (as @jaredPar pointed out). You may want to consider using Extension Methods rather than the class approach, though. It would allow you to have a "cleaner" API for getting the settings.

Sample:

public static class RadDockExtensions
{
    public static RadDockSetting GetSettings(this CormantRadDock dock)
    {
        // Implementation
    }
}

Or if you want something more generic

public static class RadDockExtensions
{
    public static U GetSettings<T,U>(this T dock)
    {
        // Implementation
    }
}

Though in this case you would need to add some constraints to actually create the implementation

It's not entirely clear to me what the purpose of the SetSettings method is, since you appear to be sending in the same object your sending to GetSettings.

In both cases you would use the above code like this:

RadDockSetting mySettings = myDock.GetSettings();

Upvotes: 1

Ssithra
Ssithra

Reputation: 710

I'm not really sure what you want to do. Maybe an extension method could do the trick rather than a method inside the interface ISetting... something like that :

public static T GetSettings<T,C>(this T t, C c) where T : ISetting<C>
{
    return t;
}

Hope this helps...

Upvotes: 0

JaredPar
JaredPar

Reputation: 754803

It looks like you just need to add another generic parameter here

public interface ISetting<T1, T2>
{
    void SetSettings(T1 obj);
    T2 GetSettings(T1 obj);
}

public class RadDockSettings : ISetting<CormantRadDock, RadDockSetting>

Upvotes: 4

Mike Miller
Mike Miller

Reputation: 16575

hmmmm might have missed the point.

but why would a settings class have a getSettings call? would it just return this?

The set takes a dock to initialise the instance, then get is merely the instance.

Upvotes: 0

Darin Dimitrov
Darin Dimitrov

Reputation: 1038930

Your question is not very clear but do you need a property:

public interface ISetting<T>
{
    T Setting { get; set; }
}

public class RadDockSetting : ISetting<CormantRadDock>
{
    public CormantRadDock Setting { get; set; }
}

Upvotes: 4

Related Questions