Generic Methods in Non-Generic Classes in c#

I’ve been using generic classes quite a bit over the last few years. However, I had never used a generic method in a non-generic class until today. I had a web service class that was using declaritive attributes to generate the WSDL. I already had a generic class, WebMethod<R>, that I was using as the base class of all my web methods to encapsulate common functionality such as authentication, logging, etc. There were some things that I needed to in the web service class that I did not want to move to the generic web method class. However, I did not want to duplicate that code in each web method of the web service. Here’s the solution, a generic method in a non-generic class. This code has been simplified for demo purposes:

[WebService(Namespace="http://blah.com/SomeWebServices/",
  Description="Some web service.")]
public class SomeWebService : System.Web.Services.WebService {
	public R Run<R>(WebMethod<R> method) where R : IWebServiceResponse, new() {
		method.UserHostAddress = this.Context.Request.UserHostAddress;
		if (AppConfig.GetSetting("systemFactoryType").ToLower() == "local") {
			method.SystemFactory = new LocalSystemFactory();
		}
		return method.Run();
	}

	[WebMethod(Description = "Take Action.")]
	public ActionResponse Action(UserToken user, ActionRequest request) {
		return Run(new ActionWebMethod(user, request));
	}

	[WebMethod(Description = "Fiddle.")]
	public FiddleResponse Fiddle(UserToken user, FiddleRequest request) {
		return Run(new FiddleWebMethod(user, request));
	}
}

public abstract class WebMethod<R> where R : IWebServiceResponse, new() {
	public SystemFactory SystemFactory {
		set { _systemFactory = value; }
	}

	protected abstract void RunMethod();

	public R Run() {
		_response = new R();
		if (Login()) {
			RunMethod();
		}
		return _response;
	}
}

WebMethod initializes SystemFactory to a remoted implementation in the constructor. I wanted to be able to change that to a non-remoted implementation via the web.config. Similarly, I did not want to add Host Address to the WebMethod constructor, but when I am actually calling the web methods from the web service, I do want to record the Host Address. Without the generic method, I would end up duplicating this code in the body of each web method.

Note that I do not have to explicitly provide a type when I am calling Run, the compiler infers it for me.

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: