What is this code doing? - c#

Could someone please explain to me what the following lines of code do?
dynamic shellApplication = Activator.CreateInstance(Type.GetTypeFromProgID("Shell.Application"));
string path = System.IO.Path.GetDirectoryName(filePath);
string fileName = System.IO.Path.GetFileName(filePath);
dynamic directory = shellApplication.NameSpace(path);
dynamic link = directory.ParseName(fileName);
dynamic verbs = link.Verbs();
I've searched the msdn library, but couldn't really understand what it did.
This isn't the full code, but I undertand the rest, it is just this part that I'm struggling with.

Looks like it is retrieving the shell actions that a particular program is associated with. For example Open, Print, Edit, etc.
Open regedit and navigate to HKEY_LOCAL_MACHINE\SOFTWARE\Classes\textfile
Expand it out and look at the Shell key. The code should be returning verbs similar to that.

This creates "Shell.Application" COM object and then uses dynamic to call methods on it.
It gets all the verbs that can be called on a file.
This is basically scripting. See here and here for a sample.

To expand on Aliostad's answer, the dynamic keyword in C# allows you to call members and methods on an unknown type. This means using a dynamic variable you won't get intellisense since the compiler has no clue what members or methods the variable actually has. This is all figured out at runtime.
Here is a good explanation.

Related

Get selected items in solution with native interfaces

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

How to search function using the description of this function?

I want to find necessary function by writing some key words or phrase from description of needed function. This need in cases, when I dont remember the name of function, but I know what it must do.
For examle: I want to produce sequence from two sequences. But I dont remember the function name.
Needed function called "Zip". This function has description with my wishes.
Only what I can is to search my wishes using the sources, like Google, StackOverflow and so on. I think that Visual Studio has all opportunities to find function using only its description.
But I dont know how to do this. It would be cool to find all the functions contain needed request in description and I could choose the fitting in my case.
I recommend that you do so using reflection. Add descriptions to each method like this.
Then, you can use the GetCustomAttributes class method to get a list of descriptions:
var descriptions = (DescriptionAttribute[])
nameOfClass.GetCustomAttributes(typeof(DescriptionAttribute), false);
You can iterate through your descriptions to find the correct methods to call, and you can also do this through reflection like so:
MethodInfo methodInfo = nameOfClass.GetMethod(methodName);
object result = methodInfo.Invoke(classInstance, parametersArray);
I am sure you will want to do more error checking and handling, but this at least explains how to go about doing this.
You can then search for your methods based on how the descriptions match. I'm not how you prefer to go about doing so, but I'd be happy to help.

NRefactory code completion with FastColoredTextBox in c#

I am building a simple IDE for C#.
..and I am using FastColoredTextBox control for source code editing, with built-in autocomplete menu (http://www.codeproject.com/Articles/161871/Fast-Colored-TextBox-for-syntax-highlighting)
The problem is, that I want to use NRefactor to do automatic code completion, just like in Visual Studio.
I did some research, I found this: https://github.com/lukebuehler/NRefactory-Completion-Sample
...but I didn't understand the code, so I can't reuse it.
To be exact, what I need?
I need an function, which will take as input list of assemblies (array of strings, which are paths to DLLs), current offset, and editor's text.
And as output, I need an array of objects, which will contain name of the object, and it's type (variable, function, type, ...)
So, how do I do it?
Is it necessary to run this autocompletion code in another thread?
Thank you for answers,
VitekST
PS: Don't hate me, I'm not familiar with NRefactor...
I starts to explore NRefactory in same day you asks this question) So, I can't call myself as NRefactory expert. But I can tell you the way, how I use it.
Theoretical material: http://www.codeproject.com/Articles/408663/Using-NRefactory-for-analyzing-Csharp-code
First of all you can use a Visual Studio solution model from this sample project to make similar classes for your IDE solution format: https://github.com/icsharpcode/NRefactory/tree/master/ICSharpCode.NRefactory.ConsistencyCheck
There are three classes you need: CSharpFile, CSharpProject and Solution. Please look at its source code and you will know, how NRefactory performs syntactic analysis of code files. Note "Compilation" field of CSharpProject and "CreateResolver" method of CSharpFile.
Second you need to perform semantic analysis of code. For this purpose you need to implement
ICSharpCode.NRefactory.CSharp.Resolver.IResolveVisitorNavigator
interface. But in your case you better use existing NRefactory implementation:
ICSharpCode.NRefactory.CSharp.Resolver.FindReferencedEntities
Constructor with two parameters waits two handlers. First being executed then resolved syntax element is reference of type, contained in your solution or in the referenced assembly (like variable declaration). Second being executed when resolved syntax element is reference of some type's member (for example "(new object()).ToString()" as a reference of member "ToString" of "object" instance). First parameter of both handlers is AstNode: unresolved syntax element of code. Second parameter is corresponding resolved semantic element: IType for first handler and IMember for another. So you need to create instance of navigator with handlers, that, for example, saving syntax and corresponding semantic elements in dictionaries.
Your code can looks like this:
var solution = new Solution(slnPath);
IDictionary<AstNode, IType> typesMap = new Dictionary<AstNode, IType>();
IDictionary<AstNode, IMember> membersMap = new Dictionary<AstNode, IMember>();
var navigator = new FindReferencedEntities(typesMap.Add, membersMap.Add);
foreach (var codeFile in solution.AllFiles)
{
codeFile.CreateResolver().ApplyNavigator(navigator);
}
After execution of this code dictionaries typesMap and membersMap will containing syntax elements of code, that NRefactory able to resolve, in the keys of dictionaries, and corresponding resolved semantic in values. If you writing autocompletion, in moment of usage processed code can not be compiled with a high probability (because user write it at this moment). So, your app must use not only resolved code, but unresolved too. To get the unresolved syntax elements of code file, than user edit at this moment, you must use:
var syntaxTree = solution.Projects
.Where(p => p.Title.Equals(editableProjName))
.Files
.Where(f => f.FileName.Equals(editableFileNamePath))
.SyntaxTree;
SyntaxTree is a "ICSharpCode.NRefactory.CSharp.SyntaxTree", that inherits AstNode class. It is a root syntax node of the code file. Variable syntaxTree will contain all unresolved syntax elements of current file being edited. To move through the syntax tree you can use AstNode enumerable members like Descendants, Children, GetParent() etc. Or you can use "Visitor" pattern and AstNode method "AcceptVisitor".
While generating list for autocompletion you can use typesMap and membersMap as fast storage of declared types and its members, and syntaxTree as slow storage, if user input stay not found.
NRefactory is a very broad topic, I can't reveal it fully. And it is very sad that this powerful framework haven't got detailed documentations. But I hope my answer can help you.

Using a variable page type in Frame.Navigate

Using WinRT, I am trying to implement navigation based on the users input. I tried to use a variable page type in the Navigate method. Unfortunately it doesn't look like it accepts variables as a page type. Does anybody know a way around this?
object myPage = page2;
this.Frame.Navigate(typeof(myPage));
I could just create switch statements and put the whole instruction in each statement but that seems ungainly and hard to maintain, especially since I may end up having a great deal of page types.
Any help would be appreciated.
Thank you.
Edit: A little clarification. I am writing a quiz program that stores the quizzes in a List, however the are multiple types of quizzes that require specific page formats so I need different page types. I am storing the the Page type as a string in the List, and the list is randomized so I don't know the next page type from the current test. The quiz engine will pre read the next quiz in the queue and extract the page type and create a variable to insert into the this.Frame.Navigate command. This is where I am having the problem. Any ideas on how to get around this issue?
Thanks
There is no any "variable" type. var just allows you to write less code. Compiler substitutes return type of the expression as the variable type, there's no "magic".
You can write it like this:
object myPage;
if (???)
myPage = new Page1();
else
myPage = new Page2();
this.Frame.Navigate(myPage.GetType());
If you want to implement navigation based on the user's input, you definely need to use if or switch statement. You need to pass type of the page to Navigate() method. I don't really get what have you been trying to do with code above. I would do it by using simple if statement.

Referencing Embedded resources from other resources in c#

In my web application I include all of my JavaScripts as js files that are embedded resources in the assembly, and add them to the page using ClientScriptManager.GetWebResourceUrl(). However, in some of my js files, I have references to other static assets like image urls. I would like to make those assembly resources as well. Is there a way to tokenize the reference to the resource? e.g.
this.drophint = document.createElement('img');
this.drophint.src = '/_layouts/images/dragdrophint.gif';
Could become something like:
this.drophint = document.createElement('img');
this.drophint.src = '{resource:assembly.location.dragdrophint.gif}';
I'd suggest that you emit the web resources as a dynamic javascript associative array.
Server side code:
StringBuilder script = new StringBuilder();
script.Append("var imgResources = {};");
script.AppendFormat("imgResources['{0}'] = '{1}';",
"drophint",
Page.ClientScript.GetWebResourceUrl(Page.GetType(), "assembly.location.dragdrophint.gif"));
script.AppendFormat("imgResources['{0}'] = '{1}';",
"anotherimg",
Page.ClientScript.GetWebResourceUrl(Page.GetType(), "assembly.location.anotherimg.gif"));
Page.ClientScript.RegisterClientScriptBlock(
Page.GetType(),
"imgResources",
script.ToString(),
true);
Then your client side code looks like this:
this.drophint = document.createElement('img');
this.drophint.src = imgResources['drophint'];
this.anotherimg = document.createElement('img');
this.anotherimg.src = imgResources['anotherimg'];
Hope this helps.
I don't particularly care for the exact implementation #Jon suggests, but the idea behind it is sound and I would concur that emitting these would be a good thing to do.
A slightly better implementation, though this is all subjective to some degree, would be to create a server-side model (read: C# class(es)) that represents this dictionary (or simply use an instance of Dictionary<string, string>) and serialize that to JavaScript literal object notation. That way you are not dealing with the string hacking you see in Jon's example (if that bothers you).
I concur with Jason's assessment of the initial solution I proposed, it can definitely be improved. My solution represents an older school javascript mentality (read, pre the emergence of ajax and JSON). There are always better ways to solve a problem, which one of the reasons why StackOverflow is so cool. Collectively we are better at the craft of programming than anyone of us on our own.
Based on Jason's ideas I'd revise my initial code, and revise some of what Jason suggested. Implement a C# class with two properties, the img resource id and a property that contains the WebResourceUrl. Then, where I differ some from Jason is that rather than using a Dictionary<string, string> I'd propose using a List<MyImageResourceClass>, which you can then in turn serialize to JSON (using DataContractJsonSerializer), and emit the JSON as the dynamic script, rather than manually generating the javascript using a string builder.
Why a List? I think you may find that dictionaries when serialized to JSON, at least using the DataContractJsonSerializer (fyi available with the 3.5 framework only, with the 2.0 or 3.0 framework you'd need to bolt on aspnet ajax and use is JSON serializer), are a little more cumbersome to work with than how a list would serialize. Although that is subjective.
There are implications too with your client side code. Now on the client side you'll have an array of the JSON serialized MyImageResourceClass instances. You'd need to iterate through this array creating your img tags as you go.
Hopefully, these ideas and suggestions can help get you going! And no doubt there are other solutions. I'm interested to see what comes of this.

Categories

Resources