Мое намерение состоит в том, чтобы любые проекты-оболочки API, которые мы будем писать в будущем для сторонних или даже внутренних API-интерфейсов, которым требуется сеанс, должны будут (в соответствии с ожидаемым шаблоном команды) реализовать этот интерфейс, потому что он будет обеспечивать общность с точки зрения этих проектов-оболочек API, потому что Я знаю, что любые классы сеансов всегда будут иметь в себе 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 = "https://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). Мне нужно, чтобы свойство было статическим, чтобы получить синглтон.
Но ты не можешь. Потому что у вас не может быть статических членов в интерфейсе. Итак... да, я мог бы убрать требование шаблона интерфейса, но я действительно не хочу.
К вашему сведению, это не функциональный код выше, я занимаюсь своим первоначальным кодированием всего этого и пытаюсь разработать его наилучшим образом.
ОБНОВЛЕНИЕ:
Что касается темы фабрик, позвольте мне сделать шаг назад, чтобы дать вам больше информации о том, что я здесь делаю. Мне нужно было получить правильный пользовательский объект APIService (я создаю класс обслуживания для каждой оболочки API, с которой можно работать) в зависимости от того, для какой оболочки API я кодирую, поэтому я создал фабрику GetService (или, по крайней мере, попытался... сделано много заводов) как ниже. И в нем видно, что все методы статические, свойства и т.д.
Пример использования ниже:
FacebookService service = PhotoServiceFactory.CurrentPhotoUploadServiceFactory;
Мысли? Я просто пытаюсь сделать то же самое для сеанса, но чувствую, что хотел бы фактически раскрыть связанный сеанс внутри экземпляра конкретной службы, который я возвращаю с завода. Так, например, я мог бы сделать что-то вроде этого:
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
    }
 
                                                                     
                                                                    