Get selected items in solution with native interfaces - c#

I am trying to get all selected items in a solution and this with native code. With native code I am referring to code which does not use the DTE.
I checked the documentation and tried to find a suitable solution, however I din't come very far. What I found was the IVsUiHierarchy which contains the ExecCommand method which contains the following.
Commands that act on a specific item within the hierarchy. (If ItemID equals VSITEMID_SELECTION, the command is applied to the selected item or items.)
So I suspect the method they are talking about, is the before mentioned ExecCommand one. For one I am not quite sure how I will get to the IVsHierarchy object from a IVsHierarchy or similar, on the other hand I am not really sure on how to use the ExecCommand method properly. Additionally I am not even quite certain, if this is even the 'right way' of approaching this.
Note: I am searching for a solution which does not contain the following code in this answer.

You can use IVsMonitorSelection.GetCurrentSelection, to identify all the selected items in the solution explorer.
The above will return you an IVsMultItemSelect interface which you can use to invoke IVsMultiItemSelect.GetSelectedItems to retrieve an array of VSITEMSELECTION values.
There are a few extensibilty samples, that utilize GetSelectedItems, you can use as a reference.
Sincerely,
Ed Dore

Related

How to get the name of the Content Property in UWP?

I've tried with
public string GetContentProperty(Type type)
{
var contentPropertyAttribute = type.GetTypeInfo().GetCustomAttribute<ContentPropertyAttribute>();
return contentPropertyAttribute?.Name;
}
But it always returns null.
In WPF it works OK.
I have been looking at this for longer than I really should have, and still don't know the complete answer. I sincerely hope someone else comes along and provides a better option.
What I've found so far is that on UWP, the call to GetCustomAttributes() returns an empty enumeration. At first I thought this might have something to do with the type-stripping done for UWP assemblies, but I can reproduce the issue in a Debug build, without the "Compile with .NET Native tool chain" option enabled, so the compiled assembly should include complete type information. And even if I modify the Default.rd.xml file to include <Type Name="Windows.UI.Xaml.Markup.ContentPropertyAttribute" Dynamic="Required All"/> (on the theory that maybe the ContentPropertyAttribute type was being omitted), that doesn't help.
So, I'm at a loss as to what exactly is going on. However, in the meantime, here is a version of your method that will work:
static string GetContentProperty<TSource>()
{
return typeof(TSource).GetTypeInfo().CustomAttributes
.Where(a => a.AttributeType == typeof(ContentPropertyAttribute))
.FirstOrDefault()?.NamedArguments.Cast<CustomAttributeNamedArgument?>()
.Where(n => n.Value.MemberName == "Name")
.FirstOrDefault()?.TypedValue.Value.ToString();
}
(Rather than pass the Type object in, I just made it generic and let the method do the work of finding the type.)
In the above, I convert the CustomAttributeNamedArgument value type to a nullable type so I can use the FirstOrDefault(), which I find more convenient than having to materialize the enumeration, inspecting its length, and then retrieving the first element if it's non-empty.
The fact that this works even while the GetCustomAttributes() method does not still makes me think that this is somehow related to something that a compiled UWP assembly does that discards type information. But unfortunately, I don't know enough about that specific area of UWP to say how.
I would be the first to agree that the above is not a terribly great option. Having to get the declaration information for the attribute rather than the attribute itself, then searching for the property name in that data, and finally having to cast the untyped value property from the data back to string so it can be returned, that's all very messy and not ideal.
But it does work. So, there's that. :)

Easiest way to plot a node structure which re-groups its nodes?

The kind of structure I am talking about is shown in the picture below.
By now my DB contains each item with giver_id (the previous item) | receiver_id (the next item). When I retrieve these items in-memory, I would like to show them in a meaningful way to the user.
I have researched and this seems to be called a "vertex/edge graph". The only option I've found is QuickGraph, and I don't seem to be able to implement it in my WindowsForm application (which is my other constraint).
Anybody knows about any other options to solve this problem?
Note: my solution does not need to be perfect, it will be used internally as a helper to configure the node chain in the DB.

Update Single Item in the ObservableCollection without LINQ

I am trying to create a list of the Components running on the network. I am trying to get all the components in the ObservableCollection. ObservableCollection<ClsComponent> Now my question is if one of the component in the collection get changed / modified how would I be able to get it reflected to my ObservableCollection of Component
Is there a way to change the it directly in the collection itself?
What is the fast and efficient way doing it?
I have tried: to change it using the LINQ : Find the Component in the collection and change it?
var CompFound = Components.FirstOrDefault(x=>x.Id == myId);
Components.Remove(CompFound);
Components.Add(UpdatedComp);
I am very sure there should have been more optimized way of doing this. Please suggest.
Edit
I am trying to write the code in the function where I can get the parameters of Source Component and Destination Component. Function looks like this
public void UpdateComponent(ClsComponent SourceComp, ClsComponent DestComp)
{
//do something here
}
After the execution of the function I want to Replace Source Component with Destination Component.
I believe this might work for you. I am sure you might be looking for this
Components.Insert(Components.IndexOf(SourceComp), DestComp);
Components.Remove(SourceComp);
One of the most efficient way would be to use a dictionary. There are implementations of ObservableDictionary which will give you the Observable behavior while allowing a fast key-based access to the object.
Check this stackoverflow question. It includes Microsoft's
It should work like ObservableCollection, except it's also a dictionary. So you can Create ObservableDictionary<Int,ClsComponent>
To replace the value simply call
Components[myId] = destComp

Updating Code, Find All Objects Of Type

Task:
Rip through all the code in the entire solution and wrap all webservice method-calls in another ws method-call that accepts a GUID (it's a login scenario)
Background :
Hundreds of web services, add token security. As explained to me when I was assigned to the task, we do it this way because if, in the future , some changes to security etc have to be made we can just do it in the WrappermethodClass in stead of having to change hundreds of web services
Tried and failed :
Find all references : too much data , returned more than 1000 hits , most of which are useless as they're only object references.
Rename WS so all references beak, build the project I'm working on and fix as I go : works well with the services not integral to the functionality but as soon as I do it with an important one it's like I shot the Solution through the brain, everything's f****d and and VS just gives up trying.
Current Solution :Open all relevant docs, Find ,select All Open Docs, skip through.
Question : How do I do this as efficiently as possible?
Code (before) :
wsGeneric wsGen = new wsGeneric();
wsGen.DoSomething();
Code (after) :
WrapperMethodClass.DoCheck takes params of (Action, GUID),
wsGeneric wsGen = new wGeneric();
wrapperMethodClass.DoCheck((g) =>
{ wsGen.UserInfo.token = g.ToString();
wsGen.DoSomething();
},Shell.token.Value);
Don´t you have some sort of interface or class where you changed the method signature already?
If you changed your webservice and your Code still compiles i´d say you did something wrong or i don´t understand the question.
Update:
I still don´t get it.
I think you have these options:
Change the method signature (all calls should be broken now, fix all the errors vs gives you and you should be done)
Find all references (of the method, not your webservice-class) and change the calls
If above isn´t possible use "Find in Files" and search for the method-name
If all your webservices inherit from an interface or base class you can refactor this method to add a parameter, all inheriting classes will also have the parameter.
If you pass a login object to each webservice, you can add a GUID element to this object and you're done.
It would be a lot easier if you showed us some code, some function interfaces that you have to change and how.
A better solution may be to just use PostSharp to add the checks to your services. This will solve your business problem (you only need to update your aspects) and is much less error prone then your current approach since you don't have to wory about some new developer forgetting to make the call to DoCheck.
Not having to find all references is a side benefit.

C#: Attrbute for intellisense to show method only outside of assembly

Basically what I'm hoping for is something that would work like how the Obsolete attribute works with Intellisense and strikes the method text when typing out the name. What I'm looking for is an attribute that blocks the method from being seen with the assembly it's defined. Kind of like an reverse internal. Using 3.5 by the by.
Yeah sounds odd but if you need the reason why, here it is:
My current solution for lazy loading in entity framework involves having the generated many to one or one to one properties be internal and have a facade? property that is public and basically loads the internal property's value:
public ChatRoom ParentRoom
{
get
{
if(!ParentRoomInnerReference.IsLoaded)
{
ParentRoomInnerReference.Load();
}
return ParentRoomInner;
}
set
{
ParentRoomInner = value;
}
}
Problem with this is if someone tries to use the ParentRoom property in a query:
context.ChatItem.Where(item => item.ParentRoom.Id = someId)
This will blow up since it doesn't know what to do with the facade property when evaluating the expression. This isn't a huge problem since the ParentRoomInner property can be used and queries are only in the entity assembly. (IE no selects and such in the UI assembly) The only situation comes in the entity assembly since it can see both properties and it's possible that someone might forget and use the above query and blow up at runtime.
So it would be nice if there were an attribute or some way to stop the entity assembly from seeing (ie blocked by intellisense) the outward facing properties.
Basically inside the assembly see ParentRoomInner. Outside the assembly see ParentRoom. Going to guess this isn't possible but worth a try.
I do see that there is an attribute
for stopping methods from being
viewable
(System.ComponentModel.EditorBrowsable)
but it's choices are rather slim and
don't really help.
You can use the EditorBrowsableAttribute for this:
[System.ComponentModel.EditorBrowsable(System.ComponentModel.EditorBrowsableState.Never)]
public void MyMethod() {}
One thing to know, though: In c#, you will still get intellisense on the method if it is in the same assembly as the one you are working in. Someone referencing your assembly (or your project, for a project reference) will not see it though. You can also pass EditorBrowsableState.Advanced, and then you will only get intellisense if c# if you clear the HideAdvancedMembers option in Tools Options.
I haven't heard of a good way to do this in plain .NET. But, here are some ideas. Maybe one of them will work, or set you off in a direction that will be helpful.
Use FxCop, probably writing your own rule to make sure ParentRoom isn't called from the asslembly that defined it.
Look into the various post-processing projects for .NET (link design-by-contract).
Write some code inside your ParentRoom getter which will check the stack (using "new Stack()" or "new StackFrame(1)" to figure out whether the caller was from the same assembly. If so, either throw an exception or simply return ParentRoomInner.

Categories

Resources