// todo: extensionRootType:将会由 IExtensionPoint<TExtension, TExtensionRoot> 的实现类所在的程序集去引用 ExtensionType 和 ExtensionRootType 所在的程序集,最后的结果会添加到 ReferencedAssemblies,此处不必解析 // apply some rules to extension point. protected bool ApplyRules(ResolutionResult resolutionResult, ResolutionContext ctx, out TypeResolution extensionType, out TypeResolution extensionRootType) { var result = true; if (!Type.IsClass || Type.IsAbstract) { resolutionResult.AddError(string.Format("The specified extension point type [{0}] is not a concrete class!", Type.TypeName)); result = false; } //// An extension point can be declared in an addin (extension schema), yet defined in another addin, thus we don't need the following check. //if (!this.DeclaresInSameAddin()) //{ // resolutionResult.AddError(string.Format( // "The extension point type [{0}] is expected to be defined and declared in a same addin, while its defining addin is [{1}], and its declaring addin is [{2}], which is not the same as the former!", // Type.TypeName, Type.Assembly.DeclaringAddin.AddinId.Guid, DeclaringAddin.AddinId.Guid)); // result = false; //} extensionRootType = null; if (!this.InheritFromExtensionPointInterface(resolutionResult, ctx, out extensionType)) { resolutionResult.AddError(string.Format("The specified extension point type [{0}] does not implement the required interface (IExtensionPoint<TExtension, TRoot>)!", Type.TypeName)); result = false; } if (!this.Type.HasPublicParameterLessConstructor()) { resolutionResult.AddError(string.Format("The specified extension point type [{0}] do not have a public parameter-less constructor!", Type.TypeName)); result = false; } return(result); }
bool ApplyRules(ResolutionResult resolutionResult, ResolutionContext ctx) { var result = true; if (!Type.IsClass || Type.IsAbstract) { resolutionResult.AddError(string.Format("The specified addin activator type [{0}] is not a concrete class!", Type.TypeName)); result = false; } if (!this.DeclaresInSameAddin()) { resolutionResult.AddError(string.Format( "The addin activator type [{0}] is expected to be defined and declared in a same addin, while its defining addin is [{1}], and its declaring addin is [{2}], which is not the same as the former!", Type.TypeName, Type.Assembly.DeclaringAddin.AddinId.Guid, DeclaringAddin.AddinId.Guid)); result = false; } if (!this.InheritFromAddinActivatorInterface(resolutionResult, ctx)) { resolutionResult.AddError(string.Format("The specified addin activator type [{0}] does not implement the required interface (IAddinActivator)!", Type.TypeName)); result = false; } if (!this.Type.HasPublicParameterLessConstructor()) { resolutionResult.AddError(string.Format("The specified addin activator type [{0}] do not have a public parameter-less constructor!", Type.TypeName)); result = false; } return(result); }
internal override bool Introspect(INameConvention nameConvention, ResolutionResult resolutionResult) { var result = true; if (ExtensionPointName == null) { resolutionResult.AddError("An id of extension point must have an parent!"); result = false; } if (ParentPath == null) { resolutionResult.AddError("An extension builder must have an parent!"); result = false; } if (TypeName.IsNullOrWhiteSpace()) { resolutionResult.AddError("An extension builder must at least provide a type name!"); result = false; } if (Name != nameConvention.GetExtensionBuilderName(TypeName)) { resolutionResult.AddError("The extension builder name and its type name does not comply with the name convention!"); result = false; } return(result | DoIntrospect(nameConvention, resolutionResult, "extension builder")); }
internal override bool Introspect(INameConvention nameConvention, ResolutionResult resolutionResult) { var result = true; if (ExtensionPointName == null) { resolutionResult.AddError("An id of extension point must have an parent!"); result = false; } if (ParentPath == null) { resolutionResult.AddError("An extension builder must have an parent!"); result = false; } return(result | DoIntrospect(nameConvention, resolutionResult, "extension builder")); }
internal bool TryParse(ResolutionResult resolutionResult, AddinResolution addin, out bool enabled, out AddinHeaderResolution result) { result = new AddinHeaderResolution { AddinId = new AddinId() }; try { enabled = Enabled == null ? true : bool.Parse(Enabled); result.AddinId.Guid = new Guid(Guid); result.AddinCategory = AddinCategory == null ? Core.AddinCategory.User : (AddinCategory)Enum.Parse(typeof(AddinCategory), AddinCategory); result.Version = Version == null ? _defaultVersion : new Version(Version); result.CompatVersion = CompatVersion == null ? _defaultVersion : new Version(CompatVersion); } catch (Exception e) { enabled = false; resolutionResult.AddError(string.Format("An exception is thrown while parsing the addin [{0}]! Error: [{1}]", Name, e.Message)); return(false); //throw new AccessViolationException(e.Message); } result.Name = Name; result.Description = Description; //result.Url = Url; result.InnerProperties = Properties; return(true); }
// The resolution of an extension point depends on the existence of its implementation type (IExtensionPoint<TExtension, TRoot>), // extension type (TExtension) and root type (TRoot), and it needs to obey some rules. protected override ResolutionStatus DoResolve(ResolutionResult resolutionResult, ConvertionManager convertionManager, ResolutionContext ctx) { if (Type == null) { Type = ctx.GetUniqueAddinType(DeclaringAddin, TypeName); if (Type == null) { resolutionResult.AddError(string.Format("Can not find the specified extension point type [{0}]!", TypeName)); return(ResolutionStatus.Failed); } TypeResolution extensionType, extensionRootType; if (!ApplyRules(resolutionResult, ctx, out extensionType, out extensionRootType)) { return(ResolutionStatus.Failed); } ExtensionType = extensionType; ExtensionRootType = extensionRootType; if (Type.Assembly.DeclaringAddin != null && !ReferenceEquals(Type.Assembly.DeclaringAddin, DeclaringAddin)) { AssemblyResolutionSet assemblySet; if (!ctx.TryGetAssemblySet(Type.Assembly.AssemblyKey, out assemblySet)) { throw new Exception(); } DeclaringAddin.AddReferencedAssemblySet(assemblySet); } } return(ResolveType(Type)); }
protected override ResolutionStatus DoResolve(ResolutionResult resolutionResult, ConvertionManager convertionManager, ResolutionContext ctx) { if (Type == null) { Type = ctx.GetUniqueAddinType(DeclaringAddin, TypeName); if (Type == null) { resolutionResult.AddError(string.Format("Can not find the specified addin activator type [{0}]!", TypeName)); return(ResolutionStatus.Failed); } if (!ApplyRules(resolutionResult, ctx)) { return(ResolutionStatus.Failed); } //if (Type.Assembly.DeclaringAddin != null && // !ReferenceEquals(Type.Assembly.DeclaringAddin, DeclaringAddin)) //{ // AssemblyResolutionSet assemblySet; // if (!ctx.TryGetAssemblySet(Type.Assembly.AssemblyKey, out assemblySet)) // throw new Exception(); // DeclaringAddin.AddReferencedAssemblySet(assemblySet); //} } return(ResolveType(Type)); }
internal bool Introspect(string addinLocation, ResolutionResult resolutionResult) { if (Guid.IsNullOrWhiteSpace()) { resolutionResult.AddError(string.Format("The addin located at [{0}] does not provide a valid guid to be identified!", addinLocation)); return(false); } if (Name.IsNullOrWhiteSpace()) { resolutionResult.AddError(string.Format("The addin located at [{0}] does not provide an addin name!", addinLocation)); return(false); } if (!_regex.IsMatch(Name)) { resolutionResult.AddError(string.Format("The addin located at [{0}] does not provide a valid name! An addin name can only contains numbers, letters or underscores!", Name)); return(false); } return(true); }
internal override bool Introspect(INameConvention nameConvention, ResolutionResult resolutionResult) { var result = true; if (AddinHeader == null) { resolutionResult.AddError( string.Format("The addin located at [{0}] does not define any addin properties (name, guid, etc) in the Addin node of manifest file, which is required!", ManifestFile.Directory)); result = false; } else { result &= AddinHeader.Introspect(ManifestFile.Directory, resolutionResult); } if (!result) { return(false); } if (AddinActivator != null) { result &= AddinActivator.Introspect(resolutionResult); } if (ExtensionSchema == null && Extensions == null) { resolutionResult.AddError(string.Format( "A valid addin manifest file must contain either an extension schema node, or an extension node, or both, while the addin [{0}] located at [{1}] does not provide any of them!", AddinHeader.Name, ManifestFile.Directory)); result = false; } if (ExtensionSchema != null) { result &= ExtensionSchema.Introspect(nameConvention, resolutionResult); } if (Extensions != null) { result &= Extensions.Introspect(resolutionResult); } return(result); }
internal bool Introspect(ResolutionResult resolutionResult) { bool result = true; if (TypeName.IsNullOrWhiteSpace()) { resolutionResult.AddError("An addin activator must have at least a type name!"); result = false; } return(result); }
internal bool Introspect(ResolutionResult resolutionResult) { if (ParentPath == null) { resolutionResult.AddError(""); return(false); } if (_children == null) { resolutionResult.AddError(""); return(false); } var result = true; foreach (var child in _children) { result &= child.Introspect(resolutionResult); } return(result); }
internal bool Introspect(INameConvention nameConvention, ResolutionResult resolutionResult) { var result = true; if (TypeName.IsNullOrWhiteSpace()) { resolutionResult.AddError("An extension point must at least provide a type name!"); result = false; } return(result | DoIntrospect(nameConvention, resolutionResult, "extension point")); }
internal bool Introspect(INameConvention nameConvention, ResolutionResult resolutionResult) { if (ParentPath == null) { resolutionResult.AddError(""); return(false); } if (_children == null) { resolutionResult.AddError(""); return(false); } foreach (var child in _children) { if (!child.Introspect(nameConvention, resolutionResult)) { return(false); } } return(true); }
internal bool Introspect(ResolutionResult resolutionResult) { var result = true; if (!Id.IsNullOrWhiteSpace() && Id.Contains(SysConstants.PathSeparatorString)) { resolutionResult.AddError("The Id property of an extension can not contains slash (/)!"); result = false; } if (!SiblingId.IsNullOrWhiteSpace() && SiblingId.Contains(SysConstants.PathSeparatorString)) { resolutionResult.AddError("The SiblingId property of an extension can not contains slash (/)!"); result = false; } if (ExtensionBuilderPath.IsNullOrWhiteSpace()) { resolutionResult.AddError("The extension builder path of an extension can not be null or empty!"); result = false; } return(result); }
protected bool DoIntrospect(INameConvention nameConvention, ResolutionResult resolutionResult, string name) { var result = true; if (Name.IsNullOrWhiteSpace()) { resolutionResult.AddError("An " + name + " must at least have an name to be identified!"); result = false; } if (Name.Contains(SysConstants.PathSeparatorString)) { resolutionResult.AddError("An " + name + " name can not contain [/]!"); result = false; } if (_children != null) { foreach (var child in _children) { result &= child.Introspect(nameConvention, resolutionResult); } } return(result); }
protected override ResolutionStatus DoResolve(ResolutionResult resolutionResult, ConvertionManager convertionManager, ResolutionContext ctx) { if (Parent != null && ExtensionBuilder != null) { // all dependencies that might be declared in other addins has been retrieved. if (Head.SiblingId != null && Sibling != null) { return(ResolveAddin(ExtensionBuilder) | ResolveAddin(Parent) | ResolveAddin(Sibling)); } if (Head.SiblingId == null) { return(ResolveAddin(ExtensionBuilder) | ResolveAddin(Parent)); } } if (Parent == null) { ExtensionPointResolution epResolution; if (!ctx.TryGetExtensionPoint(resolutionResult, Head.ParentPath, out epResolution)) { ExtensionResolution exResolution; if (!ctx.TryGetExtension(resolutionResult, Head.ParentPath, out exResolution)) { resolutionResult.AddError(string.Format("Can not find the parent of the specified extension [{0}] with path [{1}]!", Head.Path, Head.ParentPath)); return(ResolutionStatus.Failed); } if (!ReferenceEquals(exResolution.DeclaringAddin, DeclaringAddin)) { if (exResolution.DeclaringAddin.ResolutionStatus != ResolutionStatus.Success) { return(exResolution.DeclaringAddin.ResolutionStatus); // 上级对象解析 failed,子对象解析就 failed。上级 pending,此处也是 pending。 } DeclaringAddin.AddExtendedAddin(exResolution.DeclaringAddin); } //if (!ReferenceEquals(exResolution.DeclaringAddin, DeclaringAddin)) //{ var ep = GetExtensionPointFor(exResolution); if (ep == null) { return(ResolutionStatus.Pending); // the extension point is probably not available right now. } DeclaringAddin.AddExtendedExtensionPoint(ep); //} Parent = exResolution; } else { if (!ReferenceEquals(epResolution.DeclaringAddin, DeclaringAddin)) { if (epResolution.DeclaringAddin.ResolutionStatus != ResolutionStatus.Success) { return(epResolution.DeclaringAddin.ResolutionStatus); // 上级对象解析 failed,子对象解析就 failed。上级 pending,此处也是 pending。 } DeclaringAddin.AddExtendedAddin(epResolution.DeclaringAddin); } //if (!ReferenceEquals(epResolution.DeclaringAddin, DeclaringAddin)) DeclaringAddin.AddExtendedExtensionPoint(epResolution); Parent = epResolution; } } if (ExtensionBuilder == null) { ExtensionBuilderResolution eb; // the extension builder might be declared in: // 1. the same addin where this extension is declared or other affected addins (use the uid to get the extension builder directly) // 2. an updated addin (use the uid to get the extension builder path, and then use that path to get the extension builder) if (!ctx.TryGetExtensionBuilder(resolutionResult, Head.ExtensionBuilderUid, out eb)) { string extensionBuilderPath; if (!ctx.TryGetExtensionBuilderPath(resolutionResult, Head.ExtensionBuilderUid, out extensionBuilderPath)) { return(ResolutionStatus.Failed); } if (!ctx.TryGetExtensionBuilder(resolutionResult, extensionBuilderPath, out eb)) { return(ResolutionStatus.Failed); } } // The type of extension builder must be loaded before this extension, and it might not defined in the same // addin as current extension (ex), so we needs to add its declaring addin as a reference. // !!!Note that the extension point type, as well as extension type (T of IExtensionBuilder<T> implmentation) // must be loaded before this extension too, but we'll let the extension builder to reference them. if (!ReferenceEquals(eb.DeclaringAddin, DeclaringAddin)) { if (eb.Type == null) { return(ResolutionStatus.Pending); } if (!ReferenceEquals(eb.Type.Assembly.DeclaringAddin, DeclaringAddin)) { AssemblyResolutionSet assemblySet; if (!ctx.TryGetAssemblySet(eb.Type.Assembly.AssemblyKey, out assemblySet)) { throw new Exception(); } DeclaringAddin.AddReferencedAssemblySet(assemblySet); } } ExtensionBuilder = eb; } if (Head.SiblingId != null && Sibling == null) { ExtensionResolution sibling; if (!ctx.TryGetExtension(resolutionResult, Head.SiblingPath, out sibling)) { resolutionResult.AddError(string.Format("Can not find the sibling extension of the specified extension [{0}] with path [{1}]!", Head.Path, Head.SiblingPath)); return(ResolutionStatus.Failed); } // The metadata of the sibling extension must be loaded before this extension, so we needs to add its declaring // addin as a dependency. if (!ReferenceEquals(sibling.DeclaringAddin, DeclaringAddin)) { if (sibling.DeclaringAddin.ResolutionStatus != ResolutionStatus.Success) { return(sibling.DeclaringAddin.ResolutionStatus); // 上级对象解析 failed,子对象解析就 failed。上级 pending,此处也是 pending。 } DeclaringAddin.AddExtendedAddin(sibling.DeclaringAddin); } Sibling = sibling; } if (!ApplyRules(resolutionResult, ctx, convertionManager)) { return(ResolutionStatus.Failed); } return(Sibling != null ? ResolveAddin(ExtensionBuilder) | ResolveAddin(Parent) | ResolveAddin(Sibling) : ResolveAddin(ExtensionBuilder) | ResolveAddin(Parent)); }
// if we can find the referenced extension builder, the resolution is done. protected override ResolutionStatus DoResolve(ResolutionResult resolutionResult, ConvertionManager convertionManager, ResolutionContext ctx) { // Tries to get the parent if (Parent == null) { BaseExtensionPointResolution objParent; if (ParentIsExtensionPoint) { ExtensionPointResolution parent; if (!ctx.TryGetExtensionPoint(resolutionResult, ParentPath, out parent)) { resolutionResult.AddError(string.Format("Can not find the parent of the specified extension builder [{0}] with path [{1}]!", TypeName, ParentPath)); return(ResolutionStatus.Failed); } Parent = parent; DeclaringAddin.AddExtendedExtensionPoint(parent); objParent = parent; } else { ExtensionBuilderResolution parent; if (!ctx.TryGetExtensionBuilder(resolutionResult, ParentPath, out parent)) { resolutionResult.AddError(string.Format("Can not find the parent of the specified extension builder [{0}] with path [{1}]!", TypeName, ParentPath)); return(ResolutionStatus.Failed); } Parent = parent; var ep = GetExtensionPointFor(parent); if (ep == null) { return(ResolutionStatus.Pending); // the extension point is probably not available right now. } DeclaringAddin.AddExtendedExtensionPoint(ep); objParent = parent; } if (objParent.DeclaringAddin != null && !ReferenceEquals(objParent.DeclaringAddin, DeclaringAddin)) { if (objParent.Type == null) { return(ResolutionStatus.Pending); } // The parent of current extension builder is not defined in the same addin as it is, // so we needs to add its declaring addin as a reference (the type of the parent must // be loaded before this extension builder at start up). AssemblyResolutionSet assemblySet; if (!ctx.TryGetAssemblySet(objParent.Type.Assembly.AssemblyKey, out assemblySet)) { throw new Exception(); } DeclaringAddin.AddReferencedAssemblySet(assemblySet); } } if (_referenced == null) { var referenced = TryFindReferencedExtensionBuilder(Parent, Name); if (referenced == null) { if (!ctx.TryGetExtensionBuilder(resolutionResult, Path, out referenced)) { return(ResolutionStatus.Failed); } } if (referenced.DeclaringAddin != null && !ReferenceEquals(referenced.DeclaringAddin, DeclaringAddin)) { if (referenced.Type == null) { return(ResolutionStatus.Pending); } // The parent of current extension builder is not defined in the same addin as it is, // so we needs to add its declaring addin as a reference (the type of the parent must // be loaded before this extension builder at start up). AssemblyResolutionSet assemblySet; if (!ctx.TryGetAssemblySet(referenced.Type.Assembly.AssemblyKey, out assemblySet)) { throw new Exception(); } DeclaringAddin.AddReferencedAssemblySet(assemblySet); } _referenced = referenced; } return(ResolveAddin(Parent) | _referenced.Resolve(resolutionResult, convertionManager, ctx)); }
// The resolution of an extension builder depends on the existence of its implementation type // (IExtensionBuilder<TExtension> / ICompositeExtensionBuilder<TExtension>) and extension type (TExtension), // and it obey some rules. protected override ResolutionStatus DoResolve(ResolutionResult resolutionResult, ConvertionManager convertionManager, ResolutionContext ctx) { // Tries to get the parent if (Parent == null) { //BaseExtensionPointResolution objParent; if (ParentIsExtensionPoint) { ExtensionPointResolution parent; if (!ctx.TryGetExtensionPoint(resolutionResult, ParentPath, out parent)) { resolutionResult.AddError(string.Format("Can not find the parent of the specified extension builder [{0}] with path [{1}]!", TypeName, ParentPath)); return(ResolutionStatus.Failed); } if (!ReferenceEquals(parent.DeclaringAddin, DeclaringAddin)) { if (parent.DeclaringAddin.ResolutionStatus != ResolutionStatus.Success) { return(parent.DeclaringAddin.ResolutionStatus); // 上级对象解析 failed,子对象解析就 failed。上级 pending,此处也是 pending。 } if (parent.Type == null) { return(ResolutionStatus.Pending); } // The parent of current extension builder is not defined in the same addin as it is, // so we needs to add its declaring addin as a reference (the type of the parent must // be loaded before this extension builder at start up). AssemblyResolutionSet assemblySet; if (!ctx.TryGetAssemblySet(parent.Type.Assembly.AssemblyKey, out assemblySet)) { throw new Exception(); } DeclaringAddin.AddReferencedAssemblySet(assemblySet); } Parent = parent; DeclaringAddin.AddExtendedExtensionPoint(parent); //objParent = parent; } else { ExtensionBuilderResolution parent; if (!ctx.TryGetExtensionBuilder(resolutionResult, ParentPath, out parent)) { resolutionResult.AddError(string.Format("Can not find the parent of the specified extension builder [{0}] with path [{1}]!", TypeName, ParentPath)); return(ResolutionStatus.Failed); } if (!ReferenceEquals(parent.DeclaringAddin, DeclaringAddin)) { if (parent.DeclaringAddin.ResolutionStatus != ResolutionStatus.Success) { return(parent.DeclaringAddin.ResolutionStatus); // 上级对象解析 failed,子对象解析就 failed。上级 pending,此处也是 pending。 } if (parent.Type == null) { return(ResolutionStatus.Pending); } // The parent of current extension builder is not defined in the same addin as it is, // so we needs to add its declaring addin as a reference (the type of the parent must // be loaded before this extension builder at start up). AssemblyResolutionSet assemblySet; if (!ctx.TryGetAssemblySet(parent.Type.Assembly.AssemblyKey, out assemblySet)) { throw new Exception(); } DeclaringAddin.AddReferencedAssemblySet(assemblySet); } Parent = parent; var ep = GetExtensionPointFor(parent); if (ep == null) { return(ResolutionStatus.Pending); // the extension point is probably not available right now. } DeclaringAddin.AddExtendedExtensionPoint(ep); //objParent = parent; } } if (Type == null) { Type = ctx.GetUniqueAddinType(DeclaringAddin, TypeName); if (Type == null) { resolutionResult.AddError(string.Format("Can not find the specified extension builder type [{0}]!", TypeName)); return(ResolutionStatus.Failed); } TypeResolution extensionType; if (!ApplyRules(resolutionResult, ctx, out extensionType)) { return(ResolutionStatus.Failed); } ExtensionType = extensionType; if (Type.Assembly.DeclaringAddin != null && !ReferenceEquals(Type.Assembly.DeclaringAddin, DeclaringAddin)) { AssemblyResolutionSet assemblySet; if (!ctx.TryGetAssemblySet(Type.Assembly.AssemblyKey, out assemblySet)) { throw new Exception(); } DeclaringAddin.AddReferencedAssemblySet(assemblySet); } } return(ResolveAddin(Parent) | ResolveType(Type)); }