/// <summary> /// This method returns a collection of attributes representing attributes on the <see cref="DomainService"/> <see cref="Type"/>. /// </summary> /// <param name="domainServiceType">The <see cref="DomainService"/> <see cref="Type"/>.</param> /// <returns>An <see cref="AttributeCollection"/> decorated on the <see cref="Type"/> directly as well as attributes surfaced from interface /// implementations.</returns> private static AttributeCollection GetDomainServiceTypeAttributes(Type domainServiceType) { // Get attributes from TypeDescriptor List <Attribute> attributes = new List <Attribute>(domainServiceType.Attributes().Cast <Attribute>()); // All evaluate attributes that exist in interface implementations. Type[] interfaces = domainServiceType.GetInterfaces(); foreach (Type interfaceType in interfaces) { // Merge attributes together ReflectionDomainServiceDescriptionProvider.MergeAttributes( attributes, interfaceType.Attributes().Cast <Attribute>()); } return(new AttributeCollection(attributes.ToArray())); }
/// <summary> /// Register the associated metadata provider for Types in the signature /// of the specified method as required. /// </summary> /// <param name="methodInfo">The method to register for.</param> private static void RegisterAssociatedMetadataProvider(MethodInfo methodInfo) { Type type = TypeUtility.GetElementType(methodInfo.ReturnType); if (type != typeof(void) && type.GetCustomAttributes(typeof(MetadataTypeAttribute), true).Length != 0) { ReflectionDomainServiceDescriptionProvider.RegisterAssociatedMetadataTypeTypeDescriptor(type); } foreach (ParameterInfo parameter in methodInfo.GetParameters()) { type = parameter.ParameterType; if (type != typeof(void) && type.GetCustomAttributes(typeof(MetadataTypeAttribute), true).Length != 0) { ReflectionDomainServiceDescriptionProvider.RegisterAssociatedMetadataTypeTypeDescriptor(type); } } }
public override DomainServiceDescription GetDescription() { DomainServiceDescription description = base.GetDescription(); // get all type-level attributes description.Attributes = ReflectionDomainServiceDescriptionProvider.GetDomainServiceTypeAttributes(description.DomainServiceType); // get all public candidate methods and create the operations List <ReflectionDomainOperationEntry> operationEntries = new List <ReflectionDomainOperationEntry>(); IEnumerable <MethodInfo> methodsToInspect = description.DomainServiceType.GetMethods(BindingFlags.Instance | BindingFlags.Public) .Where(p => (p.DeclaringType != typeof(DomainService) && (p.DeclaringType != typeof(object))) && !p.IsSpecialName); foreach (MethodInfo method in methodsToInspect) { // We need to ensure the buddy metadata provider is registered before we // attempt to do convention, since we rely on IsEntity which relies on // KeyAttributes being present RegisterAssociatedMetadataProvider(method); if (method.GetCustomAttributes(typeof(IgnoreAttribute), false).Length > 0) { continue; } if (method.IsVirtual && method.GetBaseDefinition().DeclaringType == typeof(DomainService)) { // don't want to infer overrides of DomainService virtual methods as // operations continue; } ReflectionDomainOperationEntry operation = new ReflectionDomainOperationEntry(description.DomainServiceType, method, (DomainOperation)(-1)); if (this.ClassifyDomainOperation(operation)) { operationEntries.Add(operation); } } foreach (DomainOperationEntry operation in operationEntries) { description.AddOperation(operation); } return(description); }
/// <summary> /// Creates and returns the description provider for the specified domain service Type. /// </summary> /// <param name="domainServiceType">The domain service Type.</param> /// <returns>The description provider.</returns> internal static DomainServiceDescriptionProvider CreateDescriptionProvider(Type domainServiceType) { // construct a list of all types in the inheritance hierarchy for the service List<Type> baseTypes = new List<Type>(); Type currType = domainServiceType; while (currType != typeof(DomainService)) { baseTypes.Add(currType); currType = currType.BaseType; } // create our base reflection provider List<DomainServiceDescriptionProvider> descriptionProviderList = new List<DomainServiceDescriptionProvider>(); ReflectionDomainServiceDescriptionProvider reflectionDescriptionProvider = new ReflectionDomainServiceDescriptionProvider(domainServiceType); // set the IsEntity function which consults the chain of providers. Func<Type, bool> isEntityTypeFunc = (t) => descriptionProviderList.Any(p => p.LookupIsEntityType(t)); reflectionDescriptionProvider.SetIsEntityTypeFunc(isEntityTypeFunc); // Now from most derived to base, create any declared description providers, // chaining the instances as we progress. Note that ordering from derived to // base is important - we want to ensure that any DSDPs the user has placed on // their DomainService directly come before an DAL providers. DomainServiceDescriptionProvider currProvider = reflectionDescriptionProvider; descriptionProviderList.Add(currProvider); for (int i = 0; i < baseTypes.Count; i++) { currType = baseTypes[i]; // Reflection rather than TD is used here so we only get explicit // Type attributes. TD inherits attributes by default, even if the // attributes aren't inheritable. foreach (DomainServiceDescriptionProviderAttribute providerAttribute in currType.GetCustomAttributes(typeof(DomainServiceDescriptionProviderAttribute), false)) { currProvider = providerAttribute.CreateProvider(domainServiceType, currProvider); currProvider.SetIsEntityTypeFunc(isEntityTypeFunc); descriptionProviderList.Add(currProvider); } } return currProvider; }