簡化并統一程序獲取WebApi對應實體數據的過程,方便對實體進行擴充。原理就是數據服務使用反射發現數據提供者,處理好泛型就行。
相關傳送門:Restful WebApi開發實踐
先來看下最后的請求效果:(插件服務總線用的是服務定位器設計模式)
PRivate IModelDataService MDS = BundleServiceBus.Current.GetInstance<IModelDataService>();//獲取對應實體數據MDS.GetDataByModel<EntityModel, Guid>(new DataParameter{ TenantId = XXX, AggregationId = XXX, SiteId = XXX, CMD = "?xxx=xxx",});//帶Id獲取MDS.GetDataByModel<EntityModel, Guid>(new DataParameter<Guid>{ TenantId = XXX, AggregationId = XXX, SiteId = XXX, DataId = XXX, CMD = "?xxx=xxx",});HTTP通訊簡單封裝:(服務端使用了SSO、OAuth做授權)
public class DataWithOAuth : IDataWithOAuthService, IBundleServiceProvider{ public string LoginUserName { get; private set; } public string accessToken { get; private set; } Uri BaseAddress { get; set; } public DataWithOAuth() { LoginUserName = "[未登錄]"; } private HttpClient GetHttpClient() { var client = new HttpClient { BaseAddress = BaseAddress }; client.SetBearerToken(AccessToken); return client; } private OAuth2Client GetOAuth2Client() { return new OAuth2Client( new Uri("[oauthUrl]"), "[oauthClient]", "[oauthSecret]"); } private AccessTokenResponse RequestToken(string username, string passWord, string scope) { var client = GetOAuth2Client(); try { return client.RequestAccessTokenUserName(username, password, scope); } catch (Exception) { return null; } } public bool SetBaseUrl(string baseUrl) { if (!string.IsNullOrWhiteSpace(baseUrl)) BaseAddress = new Uri(baseUrl); return true; } public bool Login(string userName, string passWord) { var token = RequestToken(userName, passWord, "read"); if (token != null) { LoginUserName = userName; AccessToken = token.AccessToken; return true; } return false; } #region 服務 public ReturnHTTPData Get(string url) { try { var hc = GetHttpClient(); var response = hc.GetAsync(url).Result; return new ReturnHTTPData { StatusCode = response.StatusCode.ToString(), ReasonPhrase = response.ReasonPhrase, Version = response.Version.ToString(), Content = response.Content.ReadAsStringAsync().Result }; } catch (Exception ex) { return new ReturnHTTPData { Content = "Err:" + ex.Message }; } } public ReturnHTTPData Post<T>(string url, T Data) { try { var hc = GetHttpClient(); var response = hc.PostAsJsonAsync(url, Data).Result; return new ReturnHTTPData { StatusCode = response.StatusCode.ToString(), ReasonPhrase = response.ReasonPhrase, Version = response.Version.ToString(), Content = response.Content.ReadAsStringAsync().Result }; } catch (Exception ex) { return new ReturnHTTPData { Content = "Err:" + ex.Message }; } } public ReturnHTTPData Put<T>(string url, T Data) { try { var hc = GetHttpClient(); var response = hc.PutAsJsonAsync(url, Data).Result; return new ReturnHTTPData { StatusCode = response.StatusCode.ToString(), ReasonPhrase = response.ReasonPhrase, Version = response.Version.ToString(), Content = response.Content.ReadAsStringAsync().Result }; } catch (Exception ex) { return new ReturnHTTPData { Content = "Err:" + ex.Message }; } } public ReturnHTTPData Delete(string url) { try { var hc = GetHttpClient(); var response = hc.DeleteAsync(url).Result; return new ReturnHTTPData { StatusCode = response.StatusCode.ToString(), ReasonPhrase = response.ReasonPhrase, Version = response.Version.ToString(), Content = response.Content.ReadAsStringAsync().Result }; } catch (Exception ex) { return new ReturnHTTPData { Content = "Err:" + ex.Message }; } } #endregion}由于HTTP通訊這個服務我需要插件間調用,返回的數據模型我放到了契約項目內,為了不引用其他類庫,所以根據需要對HttpResponseMessage的幾個屬性做了提取:
public class ReturnHTTPData{ public string Content { get; set; } public string StatusCode { get; set; } public string ReasonPhrase { get; set; } public string Version { get; set; } public string ErrorMessage { get { return StatusCode + ":" + ReasonPhrase + " " + Content; } }}定義數據參數的模型:
public class DataParameter{ public Guid TenantId { get; set; } public Guid AggregationId { get; set; } public Guid SiteId { get; set; } public string CMD { get; set; } public static DataParameter Empty = new DataParameter();}public class DataParameter<IdType> : DataParameter{ public IdType DataId { get; set; } public new static DataParameter<IdType> Empty = new DataParameter<IdType>();}定義一個數據服務接口:
public interface IModelDataService{ ReturnModelData<DataModelType> GetDataByModel<DataModelType, IdType>(DataParameter dataParam); ReturnModelData<DataModelType> GetDataByModel<DataModelType, IdType>(DataParameter<IdType> dataParam); ReturnModelData<DataModelType> PostDataByModel<DataModelType, IdType>(DataParameter dataParam, DataModelType data); ReturnModelData<DataModelType> PutDataByModel<DataModelType, IdType>(DataParameter<IdType> dataParam, DataModelType data); ReturnModelData<DataModelType> DeleteDataByModel<DataModelType, IdType>(DataParameter<IdType> dataParam);}返回的數據類型:
public class ReturnModelData<DataModelType> : ReturnHTTPData{ public bool IsSuccess { get; set; } public List<DataModelType> Data { get; set; } public string Message { get; set; }}實現一個數據服務:
public class ModelDataService : IModelDataService, IBundleServiceProvider{ private Dictionary<Type, object> _data = new Dictionary<Type, object>(); public ModelDataService() { var data = Assembly.GetExecutingAssembly().DefinedTypes.Where(s => s.BaseType == typeof(DataHelperBase)); foreach (var typeInfo in data) { var ife = typeInfo.GetInterfaces(); var dataHelper = Activator.CreateInstance(typeInfo); try { _data.Add(ife.First().GenericTypeArguments[0], dataHelper); } catch (Exception) { } } } public ReturnModelData<DataModelType> GetDataByModel<DataModelType, IdType>(DataParameter dataParam) { object obj; if (_data.TryGetValue(typeof(DataModelType), out obj)) { var dataProvider = obj as IDataProvider<DataModelType, IdType>; if (dataProvider != null) return dataProvider.GetData(dataParam); } return new ReturnModelData<DataModelType> { IsSuccess = false, Message = "未找到[" + typeof(DataModelType) + "]的數據提供者" }; } public ReturnModelData<DataModelType> GetDataByModel<DataModelType, IdType>(DataParameter<IdType> dataParam) { object obj; if (_data.TryGetValue(typeof(DataModelType), out obj)) {
新聞熱點
疑難解答