Visual C++: ATL Implementation of an Interface - visual-c++

I guess this is a real dumb question, but I couldn't find an answer. I'm trying to implement an COM interface using ATL. According to this I should use the Implement Interface Wizard. My question is how can I find the desired interface in this wizard. Do I have to go over all the libraries? Does is specified somewhere in the documentation of the interface (IOleCommandTarget)

To implement an interface you need:
inherit your class from it
add it onto interface map
implement its methods
For example:
class CFoo :
// regular COM object base class, esp. those generated by ATL Simple Object Class Wizard
public IOleCommandTarget
{
BEGIN_COM_MAP(CFoo)
// ...
COM_INTERFACE_ENTRY(IOleCommandTarget)
END_COM_MAP()
// ...
public:
// IOleCommandTarget
STDMETHOD(Exec)(...) // IOleCommandTarget methods go here
{
// ...
}
};

To implement you need to do:
In the *h file let your CoClass inherit from interface.
2.In the *h file ,add an interface entry in the COM Map.
In the *h file ,add the prototype of interface methods.
In the *cpp file, implement the method of interface.

Related

How to dynamic modify super classes of a class using asm or javassist

How to dynamic modify a class's super classes to point to another class as its superclass by asm or javassist?
I know how to modify a class's methods and fields.
You should take a look at setSuperclass. Here is a small example:
CtClass c = pool.getCtClass("com.my.class.A");
c.setSuperclass(pool.getCtClass("com.my.class.B"));
Here is the documentation for this method:
public void setSuperclass​(CtClass clazz)
throws CannotCompileException
Changes a super class unless this object represents an interface. The new super class must
be compatible with the old one; for example, it should inherit from
the old super class.
If this object represents an interface, this
method is equivalent to addInterface(); it appends clazz to the list
of the super interfaces extended by that interface. Note that an
interface can extend multiple super interfaces.

Ways of loading external dll and injecting conditionally multiple implementations using autofac

i have an interface called say IMyHook which has some implementation in an external project(dll). i use this interface in my businesslogic classes and on my application startup i inject external implementation of this interface using Autofac.
my interface
public interface IMyHook {
public void MyHookMethod();
}
my business logic class
public class myBusinessLogic{
// implementation injected by autofac
public IMyHook Hook {set;get;}
public void MyBusinessLogicMethod (flag){
if(Hook !=null){
Hook.MyHookMethod();
}
else{
// other code
}
}
}
auto face properties injection
var hoodAssemblyPath = "C:\\hook.dll";
builder.RegisterAssemblyTypes(hoodAssemblyPath).
AsImplementedInterfaces().PropertiesAutowired();
this works all fine but now issue is that my external dll (hook.dll) can have more then one implementations of IMyHook. And i want to decide which implementation to load in my MyBusinessLogicMethod method using the input paramameter flag. e.g
if (flag ==1)
then load implementation 1
else if (flag == 2)
then load implememtation 2
etc
i can do this using Reflections (and a custom attribute in my external classes representing each value of flag) by loading assembly and then the appropriate class using custom attribute on it.
But my question is;
is this the right way loading external dll on each method call using reflection etc or are there any other ways of doing this? using autofac or anything else?
with all this i want to let users of my application to inject their code in my application for some of the functionality. so external dll or implementations will basically be written by my users and then my application will just load and execute the methods.
Registering all the dependencies using AsImplementedInterfaces().PropertiesAutowired(); could be quite heavy and you may encounter problem on complex scenario. Furthermore, you won't be able to customize the way the registration is made for each registration (controlling lifetimescope, etc.)
I would recommend to register module that your users have to write inside these assemblies. Then load them using RegisterAssemblyModules.
if (flag ==1) then load implementation 1 else if (flag == 2) then load implememtation 2 etc
How would you decide which implementation to use ? implementation1 means implementation coming from Hook1.dll ?
A common way to do this is to use Named and Keyed Services and/or Component Metadata
If you can't ask your users to implement module you can use something like this :
builder.RegisterAssemblyTypes(hoodAssemblyPath)
.AsImplementedInterfaces()
.PropertiesAutowired()
.WithMetadata("source", "hook1");
and then
IFoo foo = container.Resolve<IEnumerable<Lazy<IFoo, String>>>()
.First(f => f.Metadata["source"] == "hook1")
.Value
If you do it this way consider using typed metadata.

Handling standard commands in custom editor

I have created a Visual Studio extension that provider syntax highlighting by implementing IClassifierProvider. I would like to add additional features such as support for the standard Edit.CommentSelection and Edit.FormatDocument commands, but I have no idea how to do that. All the documentation I can find is about adding new commands, but the commands I want to handle already exist.
How can I handle these commands?
I considering the specific Comment Selection and Uncomment Selection commands you refer to as special cases, because I'm working on a Commenter Service specifically intended to support these two actions. The service is being developed on GitHub and will be released via NuGet when it is ready. I'll start with a description of this service, and follow with some general information about implementing support for specific commands, including the Format Document command.
I would like to release the library and its dependencies this week, but the restriction that the Commenter Interfaces assembly be an immutable assembly demands more testing than is generally given to a library prior to its initial release. Fortunately the only thing in this particular assembly is two interfaces is the Tvl.VisualStudio.Text.Commenter.Interfaces namespace.
Using the Commenter Service
Source: Commenter Service (Tunnel Vision Labs' Base Extensions Library for Visual Studio)
This services allows extension developers to easily support the Comment and Uncomment commands for new languages in Visual Studio.
Providing a Standard Commenter
The easiest way to provide commenting features is to use the standard Commenter implementation of the ICommenter interface. The following steps show how to create an instance of Commenter and provide it to the Commenter Service by exporting an instance of ICommenterProvider.
Create a new class derived from ICommenterProvider. This class is exported using the MEF ExportAttribute for one or more specific content types using the ContentTypeAttribute. The commenter in the example supports C++-style line and block comments, for the SimpleC content type.
[Export(typeof(ICommenterProvider))]
[ContentType("SimpleC")]
public sealed class SimpleCCommenterProvider : ICommenterProvider
{
public ICommenter GetCommenter(ITextView textView)
{
// TODO: provide a commenter
throw new NotImplementedException();
}
}
Define the comment format(s) the commenter will support.
private static readonly LineCommentFormat LineCommentFormat =
new LineCommentFormat("//");
private static readonly BlockCommentFormat BlockCommentFormat =
new BlockCommentFormat("/*", "*/");
Implement the GetCommenter(ITextView) method by returning an instance of Commenter. The ITextUndoHistoryRegistry service is imported in order for Commenter to correctly support the Undo and Redo commands. The following code is the complete implementation of ICommenterProvider required to support the Comment and Uncomment commands for a simple language.
[Export(typeof(ICommenterProvider))]
[ContentType("SimpleC")]
public sealed class SimpleCCommenterProvider : ICommenterProvider
{
private static readonly LineCommentFormat LineCommentFormat =
new LineCommentFormat("//");
private static readonly BlockCommentFormat BlockCommentFormat =
new BlockCommentFormat("/*", "*/");
[Import]
private ITextUndoHistoryRegistry TextUndoHistoryRegistry
{
get;
set;
}
public ICommenter GetCommenter(ITextView textView)
{
Func<Commenter> factory =
() => new Commenter(textView, TextUndoHistoryRegistry, LineCommentFormat, BlockCommentFormat);
return textView.Properties.GetOrCreateSingletonProperty<Commenter>(factory);
}
}
Command Handling in Visual Studio
The following are general steps for handling commands in Visual Studio. Keep in mind that the implementation details are quite complicated; I've created some abstract base classes to simplify specific implementations. After this overview, I will point to both those and a concrete example of their use for you to reference.
Create a class which implements IOleCommandTarget. The QueryStatus method should check for the specific commands handled by your command target and return the appropriate status flags. The Exec method should be implemented to execute the commands.
Register the command target with a specific text view by calling IVsTextView.AddCommandFilter. If you are working with an MEF-based extension, you can obtain the IVsTextView by either exporting an instance of IVsTextViewCreationListener, or by importing the IVsEditorAdaptersFactoryService component and using the GetViewAdapter method to obtain an IVsTextView from an instance of ITextView.
Here are some specific implementations of the interfaces described here:
CommandFilter: This class implements the basic requirements for IOleCommandTarget
TextViewCommandFilter: This class implements additional functionality to simplify the attachment of a command filter to a text view
CommenterFilter: This class is a concrete implementation of a command filter used by the Commenter Service implementation to handle the Comment Selection and Uncomment Selection commands

Buiding Orchard Module - Telling Autofac to use different implementations

As I exposed here, I would like to be able to query freely on the index without Orchard building the query for me.
I built a module, and inserted a copy of the SearchController, adding a new route...
To override default Orchard behavior concerning the query, I had to create new implementations of : ISearchService, IIndexManager, ISearchBuilder, IIndexProvider.
There are minor modifications from their default implementations, but they are needed.
That works as expected, but it currently override the default search too.
This is because I used the same interfaces and autofac takes my implementations.
I would like to be able to leave the default implementation untouched (at url /Search), and add my implementation at url (/LuceneSearch for example)
I suppose I must tell Autofac to use my implementations only for my controller by creating a class that inherits the autofac Module class.
Here is my problem : I don't know how to tell Autofac to use by default the Orchard Implementation, and just for my controller, use my implementation....
Another possibility is to create new interfaces, but it seems to me not really beautiful...
Can someone help me ? :)
Metadata feature will help you here. Also you have to register your implementations with PreserveExistingDefaults() modifier to preserve orchard's implementations by default.
Update:
Orchard registers all dependencies from Autofac's IModule implementation and from Orchard's IDependency one. All magic happen in Orchard's ShellContainerFactory class. Since ISearchService inherits from IDependency your implementation is registered by Orchard which overwrites default one.
You have two ways here:
Introduce your own empty interface IMySearchService which inherits from ISearchService. Implement and use it in your code where you need your implementation. Orchard will handle all registrations for your.
Orchard registers all IDependency implementations with "Feature" Metadata in ShellContainerFactory.RegisterType method. You can read this metadata in your code and choose your implementation (see link to wiki above). Feature class contains all necessary information about your module.
Hope this will help you.
A simpler method without dabbling with the intricacies of Autofac would be to use an IEnumerable<IInterface> variable in your controller/driver at url "/LuceneSearch" to hold all implementations of IInterface and choose which to consume.
For example, in order to consume your implementation of IIndexManager, you would put the following in your controller or driver
public class MyCustomPartDriver : ContentPartDriver<MyCustomPart> {
private readonly IEnumerable<IIndexManager> _indexManagers;
public MyCustomPartDriver(IEnumerable<IIndexManager> indexManagers) {
_indexManagers = indexManager;
}
protected override DriverResult Display(MyCustomPart part, string displayType, dynamic shapeHelper) {
//Use your implementation of IIndexManager
var indexManager = _indexManagers.First(im => im is MyCustomIndexManager);
//Get the ISearchBuilder from your implementation of IIndexManager
var searchBuilder = indexManager.HasIndexProvider() ? indexManager.GetSearchIndexProvider().CreateSearchBuilder("Search") : new NullSearchBuilder();
//perform search on the indexing engine
var contentItemIds = searchBuilder.
.WithField("type", "MyCustomType").Mandatory().ExactMatch()
.Parse("mycustompart-keyword", part.Keyword).Mandatory()
.Search()
.Select(h => h.ContentItemId)
.ToList();
//do stuff with the results returned and return a DriverResult using the ContentShape method. Well, you know the drill.
}
}
If you don't want to have autofac resolve your own implementation by default, then don't implement the public interface.

How do I make a public view model base with WinRT classes?

I wanted to create an abstract base class for all of my view models, but I'm running into accessibility issues and can't seem to navigate through the errors. Here's an example of my code:
public ref class ViewModelBase {
...
}
public ref class OtherViewModel : ViewModelBase {
...
}
When I define my code as state above, I get the following error:
error C4585: 'MyNamespace::ViewModelBase' : A WinRT 'public ref class' must either be sealed or derive from an existing unsealed class
If, instead, I make ViewModelBase private, I get this error:
error C3213: base class 'MyNamespace::ViewModelBase' is less accessible than 'OtherViewModel'
This seems like it should be incredibly simple. What am I doing wrong?
What you are attempting is not strictly possible in C++/CX, as in VS 2012 C++/CX does not support public class inheritance for general-purpose scenarios. It is only supported enough to have the XAML scenarios work; the only possible public unsealed types are those found under the Windows::UI::Xaml namespace, and users are not able to author their own public unsealed types.
If you want to have a base class for all your view models, your only options to make all your classes private or to inherit from a base class from Windows::UI::Xaml (such as DependencyObject).
Each of these approaches has drawbacks:
using DependencyObject as your base makes all your viewmodels STA objects (so they can only be manipulated from the UI thread) in addition to having a lot of overhead that isn't really necessary.
Making your classes private means you cannot use the [Bindable] attribute to do databinding, so you would need to have a private databinding implementation. (Your private class would need to implement ICustomPropertyProvider and related interfaces.)
The "sealed" keyword means that the class cannot be inherited from. Your implementation should look something like this:
ref class ViewModelBase sealed
If you want to inherit from ViewModelBase then you need to have only the subclasses be ref classes like this:
class ViewModelBase
...
public ref class OtherViewModel sealed : ViewModelBase

Resources