Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
649 views
in Technique[技术] by (71.8m points)

c# - What's the correct way to let people use the types in an AddOn that I've loaded

I have a class library (CoreLib) which exposes a bunch of functionality, both out-of-the box and through add-ons.

The interface for interacting with addons is very general (on purpose), where each addon can return metadata describing the properties it exposes. The base class for addons looks something like this:

public abstract class AddOnBase 
{
  public abstract IList<PropertyDescriptor> GetPropertyDescriptors();
  public void SetPropertyValue(Guid propertyId, object value);
  public object GetPropertyValue(Guid propertyId);
}

This generality works very nicely for someone building a UI to expose the addon's properties.

However, if someone wants to work with the addon in plain old .NET code, it's way too cumbersome. For example:

// Declare some published IDs to identify the "Recipe" addon and its properties.
Guid recipeAddOnId = new Guid("...");
Guid recipeTitlePropId = new Guid("...");
Guid recipeCategoryPropId = new Guid("...");

AddOn addon = coreLib.GetService(IAddOnService).GetAddOnInstance(recipeAddOnId);

// Set some properties in the recipe addon.
addon.SetPropertyValue(recipeTitlePropId, "Cupcakes");
addon.SetPropertyValue(recipeCategoryPropId, "Baked Goods");

// Do something with the addon.
coreLib.GetService(IAddOnService).ProcessAddOn(addon);

This works fine, but there's all these GUIDs that the developer needs to look up, and it makes everything really clunky.

I would much rather the developer could add a reference to the RecipeAddOn and write something like this instead:

Guid recipeAddOnId = RecipeAddOn.Id;

AddOn addon = coreLib.GetService(IAddOnService).GetAddOnInstance(recipeAddOnId);

// Cast the instance returned by CoreLib to a RecipeAddOn
RecipeAddOn recipe = (RecipeAddOn)addon;

// Set some properties in the recipe addon.
recipe.Title = "Cupcakes";
recipe.Category = "Baked Goods";

// Do something with the addon.
coreLib.GetService(IAddOnService).ProcessAddOn(recipe);

Here, not only do they not have to mess with GUIDs to identify properties, but they get to work with more concrete classes and get intellisense to help them in their development.

My current solution is to have the developer reference both CoreLib and RecipeAddOn, with CopyLocal set to false on the latter. However, it's been suggested that this can lead to DLL hell (see Why do I need an AssemblyResolve handler for an assembly which is already loaded?), so I wanted to ask what is the proper way to do this.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

My extension setup is always like this. It's from days of C and Pascal where everybody publishes an header file or pascal unit with interface and a lib/obj file to link with.

  • Client
  • InterfaceDll
  • ImplementationDll

Client references Interface dll which contains IRecipeAddon interface. On Runtime client also loads Implementation dll, creates an instance of RecipeAddon concrete class and casts it to IRecipeAddon interface. Developer gets intellisense, and add on implementation does not mixed with client code.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...