Мое намерение состоит в том, что любые проекты-обертки API, которые мы напишем в будущем вокруг сторонних или даже внутренних API, которые нуждаются в сеансе, должны будут (в соответствии с ожидаемым шаблоном команды) реализовать этот интерфейс, потому что он обеспечит общность в терминах этих API Проекты Wrapper, потому что я знаю, что любые классы сессий всегда будут содержать GetCurrentSession, RenewSession и т. Д. ... поэтому у нас есть единообразная модель с точки зрения общих членов, которые будут реализованы для конкретных классов сессий.
Итак, вот мой интерфейс:
/// <summary>
/// Represents an API end user based session
/// </summary>
public interface IAPISession
{
#region Properties
int SessionID { get; }
/// <summary>
/// Gets the user ID.
/// Note: type string since userID is not always int in 3rd party APIs
/// </summary>
/// <value>The user ID.</value>
string UserID { get; }
bool SessionHasExpired { get; }
DateTime ExpirationDate { get; }
void LogOut(); // expires the session & sets SessionHasExpired
#endregion Properties
#region Methods
/// <summary>
/// Renews the session by returning a brand new session
/// if the existing session has expired.
/// </summary>
/// <returns></returns>
IAPISession RenewSession();
/// <summary>
/// Gets the current API session
/// </summary>
/// <returns></returns>
IAPISession GetCurrentSession();
#endregion Methods
}
Вот пример реализации:
public class FacebookSession : IAPISession
{
private static FacebookSession _singletonInstance;
private FacebookSession() { }
#region Properties
private HttpContext CurrentContext { get; set; }
private HttpCookie CurrentSessionCookie { get; set; }
#endregion
#region IAPISession Members
// Checks for a current session cookie
public bool SessionHasExpired
{
get
{
return _singletonInstance == null;
}
}
public IAPISession RenewSession()
{
throw new NotImplementedException();
}
/// <summary>
/// Gets the current API session singleton instance
/// </summary>
/// <returns></returns>
public static IAPISession GetCurrentSession()
{
if (SessionHasExpired)
{
return null;
}
// TODO: return the singleton instance here...
}
public void LogOut()
{
throw new NotImplementedException();
}
public int SessionID { get; private set; }
public string UserID { get; private set; }
public DateTime ExpirationDate { get; private set; }
#endregion
public void LogIn(HttpContext currentContext)
{
if (SessionHasExpired)
{
const string redirectUri = "http://localhost/Photo/FacebookOauth.aspx"; // page they will be redirected to after they auth
string authUrl = ConfigUtil.GetAppConfigSetting("PayPalBaseUri") + "?client_id=" +
ConfigUtil.GetAppConfigSetting("PayPalClientID") +
"&redirect_uri=" + redirectUri;
CurrentContext.Response.Redirect(authUrl); // redirect them to log in
}
}
}
и вот моя проблема. Сеанс является одиночным для текущего пользовательского потока. Чтобы получить доступ к синглтону, необходимо внедрить метод GetCurrentSession()
, который, как я знаю, все API, которые мы создаем (будет полностью отличаться в том, КАК они будут реализованы на основе API), мне нужно, чтобы свойство было статическим свойством, чтобы получить синглтон .
Но ты не можешь. Потому что вы не можете иметь статические члены в интерфейсе. Итак ... да, я мог бы убрать требование шаблона интерфейса, но я действительно не хочу.
К вашему сведению, это не функциональный код, описанный выше, я делаю свое первоначальное кодирование всего этого и пытаюсь разработать его наилучшим образом.
UPDATE:
По вопросу о фабриках позвольте мне сделать шаг назад, чтобы дать вам больше контекста в том, что я здесь делаю. Мне нужно было получить правильный пользовательский объект APIService (я создаю класс обслуживания для каждой оболочки API для работы) в зависимости от того, для какой оболочки API я кодирую, поэтому я создал фабрику GetService (или, по крайней мере, попытался ... не сделано много заводов) как ниже. И в нем видно, что все методы статические, свойства и т. Д.
Пример использования ниже:
FacebookService service = PhotoServiceFactory.CurrentPhotoUploadServiceFactory;
Мысли? Я просто пытаюсь сделать то же самое для Session, но чувствую, что хотел бы фактически показать связанный сеанс внутри экземпляра Specific Service, который я получаю с завода. Так, например, я мог бы сделать что-то вроде этого:
service.CurrentSession which would give me the current facebook singleton session.
Служба здесь имеет тип FacebookService, потому что фабрика вышла, чтобы получить его на основе типа API, с которым я работаю (тип API - это созданный мною Enum со значениями, такими как Facebook, Flickr и т. Д.)
public class PhotoServiceFactory
{
private static PhotoServiceFactory _singletonInstance;
private PhotoServiceFactory(){}
#region Properties
public static PhotoUploadServiceFactory CurrentPhotoUploadServiceFactory
{
get
{
_singletonInstance = _singletonInstance ?? (_singletonInstance = new PhotoUploadServiceFactory());
return _singletonInstance;
}
}
#endregion
#region Methods
public static IAPIService GetAPIService(APIType apiType)
{
IAPIService apiService = null;
switch (apiType)
{
// return the right service singleton instance
// based on the API type that we're working with
case APIType.Facebook:
apiService = FacebookAPIService.CurrentFacebookAPIService;
break;
case APIType.Flickr:
apiService = null; // service not implemented
break;
case APIType.PhotoBucket:
apiService = null; // service not implemented
break;
case APIType.Picasa:
apiService = null; // service not implemented
break;
case APIType.Kodak:
apiService = null; // service not implemented
break;
}
return apiService;
}
#endregion
}