I am new to c#, recently I read the source of code of Oxygen not include(using dnspy), which have some confusing code. I tried google but nothing helpful can be found.
Threr is a class called ElementEntry derived from a template class YamlIO。
what confuse me is that this template take the parameter T same as the class ElementEntry.
I think this may cause some problem. Am I right?
public class YamlIO<T>
{
...
}
public class ElementEntry : YamlIO<ElementEntry>
{
...
}
Related
I try to extend my MyDSLProposalProvider from an external Eclipse RCP Project. I created an extension point schema which requires a class property which extends my ProposalProvider. In the new project I extend the class an overrode some methods justs to give me some output so I can see that the external method is called. But this is currently not happening. Is there anything I have to consider?
Currently the hirachy looks like:
MyDSLProposalProvider extends AbstractMyDSLProposalProvider
ExternalProposalProvider extends MyDSLProposalProvider
I rewrote a Method generated in the AbstractMyDSLProposalProvider but when its triggered the predefined Method in the AbstractMyDSLProposalProvider is called and not my new implementation.
public class ExternalMyDSLProposalPovider extends MyDSLProposalProvider
{
#Override
public void completeComponent_Name(EObject model, Assignment
assignment, ContentAssistContext context,
ICompletionProposalAcceptor acceptor) {
System.err.println("extern");
if(model instanceof Component)
{
createProposal("foo", "foo", context, acceptor);
}
super.completeComponent_Name(model, assignment, context, acceptor);
}
}
This is the class in the external Eclipse Project.
Thanks for the help.
When you declare an extension point using a schema that you have defined Eclipse puts that declaration in the extension point registry. That is all that is does, you must then write code to make uses of those declarations.
You read the extension point registry using something like:
IExtensionRegistry extRegistry = Platform.getExtensionRegistry();
IExtensionPoint extPoint = extRegistry.getExtensionPoint("your extension point id");
IConfigurationElement [] elements = extPoint.getConfigurationElements();
elements is now an array of the declarations in the various plugins using the extension point.
IConfigurationElement has various methods to get the values of the attributes of the declaration.
If you have defined a class in one of the attributes you can create an instance of the class using:
IConfigurationElement element = .... a config element
Object obj = element.createExecutableExtension("attribute name");
In your case the result should be your ExternalMyDSLProposalPovider.
You will then need to hook this object up with whatever is doing to proposals.
I'm new to Eclipse 4 RCP and just learning the basics.
I created a part and gave it a class URI.
For some reason the class's constructor isn't being called.
What could be the reason?
PlaygroundPart code:
package com.example.e4.rcp.todo.parts;
public class PlaygroundPart {
public PlaygroundPart() {
System.out.print("Example");
}
}
Nothing is printed in the console.
I'm trying to implement a class instance of an interface class. Exploring the interface (.NET DLL) with the project explorer, it says:
bool CreateInstance(SharedLibrary::MemoryArbiter^ pntMemory,
SharedLibrary::clsMessageQueue^ pntMessageQueue,
SharedLibrary::clsGPIO^ pntGPIO,
SharedLibrary::Types^ pntProgramSettings,
SharedLibrary::DisplayDriver^ pntDisplayDriver)
Member from Plugin_Interface::IPlugin
But if I write in my MyClass.h:
using namespace System;
using namespace System::ComponentModel;
using namespace SharedLibrary;
namespace MyCppPlugin {
[AttributeUsageAttribute(AttributeTargets::Class | AttributeTargets::Method |
AttributeTargets::Property | AttributeTargets::Field,
AllowMultiple = true, Inherited = false)]
ref class MyPlugin abstract : public Plugin_Interface::IPlugin
{
bool CreateInstance(SharedLibrary::MemoryArbiter^ pntMemory,
SharedLibrary::clsMessageQueue^ pntMessageQueue,
SharedLibrary::clsGPIO^ pntGPIO, SharedLibrary::Types^
pntProgramSettings, SharedLibrary::DisplayDriver^ pntDisplayDriver);
};
};
It says: "error C3766: Missing implementation of Plugin_Interface::IPlugin::CreateInstace(...)
What the heck do I do wrong?
EDIT:
Forgot the abstract statement.
And: Why is it saying "IntelliSense: Class can not implement interface member function "Plugin_Interface::IPlugin::CreateInstance" (declared in "Plugin_Interface.dll")"
???
You got a lot more diagnostic messages from this snippet, you are making several mistakes:
[AttributeUsage] is only valid on a class that derives from System::Attribute. You no doubt need to use some kind of attribute so that the plugin host can recognize your class as a valid plugin candidate, I can't guess what that attribute might be.
A method that implements an interface method should be public.
A method that implements an interface method must be virtual.
The method signature must be an exact match with the interface method declaration.
Just in case: you must actually implement the method, not just declare it.
The third and forth bullets are the chief reasons for the "must provide an implementation of the interface method" compile error. So proper code ought to resemble something like this:
[NoIdeaWhatAttribute]
public ref class MyPlugin : public Plugin_Interface::IPlugin {
public:
virtual bool CreateInstance(SharedLibrary::MemoryArbiter^% pntMemory,
SharedLibrary::clsMessageQueue^% pntMessageQueue,
SharedLibrary::clsGPIO^% pntGPIO,
SharedLibrary::Types^% pntProgramSettings,
SharedLibrary::DisplayDriver^% pntDisplayDriver)
{
// Todo...
return false;
}
};
I got it. Thanks to Hans Passant who gave me so many hints :)
To export the function it has to implement the Interface 1:1. The export statement has to be added over the class header:
[Export(IPlugin::typeid)]
public ref class MyPlugin : public Plugin_Interface::IPlugin
And: While VB.NET will compile to "Any CPU" and C++/CLI will compile to Win64/Win32 it will missfit. Both Projects have to have the same target - either 64bit OR 32bit.
Now it works.
How do I register IPetFactory<TPet> to be resolved with DefaultPetFactory<TPet> where TPet can be any class based on Pet in the example below?
I'd like to be able to resolve IPetFactory<Dog> with DefaultPetFactory<Dog>.
I've just found examples using BasedOn where the Factory itself is based on a class, not the generic argument.
class Pet
{
public string Name { get; set; }
}
class Fish : Pet {}
class Dog : Pet {}
class Cat : Pet { }
interface IPetFactory<TPet> where TPet : Pet;
class DefaultPetFactory<TPet> : IPetFactory<Pet> where TPet : Pet
{
// default implementation
}
My real implementation has a lot of classes based on Pet so I'm looking for a more generic approach than just calling register on each of them.
EDIT:
I found out the problem wasn't what I thought it was. It was due to the generic arguments and an exception of “the arity of the generic type definition” which caused my problems.
And I over-simplified my example. In my real implementation I have to generic arguments and it turns out Windsor need the the same generic parameters to be able to resolve the type.
If I do like this it won't work.
class Owner
{
}
class DefaultPetFactory<TPet> : IPetFactory<Owner, TPet> where TPet : Pet
{
// default implementation
}
If I do like this it will:
class DefaultPetFactory<TOwner, TPet> : IPetFactory<TOwner, TPet>
where TOwner : Owner
where TPet : Pet
{
// default implementation
}
If anyone has a better solution to this, preferably with the registrations it's appreciated. I don't like to change my classes to make the registration work.
(For the updated question)
There is a ticket in Windsor's issue tracker to support scenarios like that (feel free to vote for it), but in general this is something very hard to implement... generically (no pun intended), and as far as I know no container currently supports it.
In Windsor 3 you can workaround it by implementing a new interface called IGenericImplementationMatchingStrategy doing roughly the following (untested, I'm writing this from memory):
public class PetMatcher: IGenericImplementationMatchingStrategy
{
public Type[] GetGenericArguments(ComponentModel model, CreationContext context)
{
if (SomePreconditionToMakeSureThatsReallyTheScenarioDescribedAbove() == false )
{
return null;// which will fallback to default behaviour
}
// implementation needs just one generic arg, second of two the interface has
return new[]{ context.GenericArguments[1] };
}
}
You then register this as follows:
Container.Register(
Classes.FromAssemblyContaining(typeof(IPetFactory<,>)).BasedOn(typeof(IPetFactory<,>))
.WithServiceBase()
.Configure(
c => c.ExtendedProperties(
Property.ForKey(ComponentModel.GenericImplementationMatchingStrategy)
.Eq(new PetMatcher()))));
Can you import using a class that inherits from Lazy rather than Lazy itself? I am exporting using a derivitive of ExportAttribute that contains metadata.
[FeatureExport(/* Feature Metadata Parameters */)]
public class Feature : IFeature
{
// Feature Properties
}
public class FeatureReference : Lazy<IFeature, IFeatureMetadata>
{
}
public class Consumer
{
[ImportMany]
public IEnumerable<FeatureReference> FeatureReferences { get; set; }
}
Is this possible? Would it work? I could try it myself, but I'm in development so I don't actually have any code written.
No, it won't work I'm afraid. You would need to implement your own programming model extension (either a custom part/catalog or possibly via ReflectionModelServices) to make this work.
MEF would have to create the FeatureReference object in order to set it, and considering that FeatureReference might have any constructor imaginable, you can guess why this isn't supported.