Here is my extension method:
Public Module HtmlExtensions
System.Runtime.CompilerServices.Extension
Public Function ReverseMapPath(ByVal html As HtmlHelper, ByVal path As String) As String
Dim appPath = HttpContext.Current.Server.MapPath("~")
Dim res As String = String.Format("{0}", path.Replace(appPath, "/").Replace("\", "/"))
Return res
End Function
End Module
My web.config has an entry for my namespace
Everything was working just fine. I started adding more code to the project and now I get an error that looks like I am loading the extension method twice but I cannot figure out why. The error is:
path.page.vbhtml(9): error BC30521: Overload resolution failed because no accessible 'FunctionName' is most specific for these arguments:
Extension method 'Public Function FunctionName(path As String) As String' defined in 'namespace.Extensions.HtmlExtensions': Not most specific.
Extension method 'Public Function FunctionName((path As String) As String' defined in 'namespace.Extensions.HtmlExtensions': Not most specific.
I don't understand why this has just crept up. Clearly I changed something but undoing everything doesn't help. The error seems more behind the .net framework. Any ideas?
I just ran into this issue. If you read the link CrazyTim commented, the problem comes from VS adding a reference in the project to itself.
If you're running into this issue, VS might have added a reference in your project to itself. Delete the reference, and you'll be right as rain.
It appears that it was a namespace issue. My extension class had Global.ProjectName as the namespace. Once I changed that everything worked. It must have been loading it twice due to the namespace.
Related
I am building a small helper to fetch and populate all the controls of a ribbon group inside a collection.
Option Strict On
Imports Microsoft.Office.Tools.Ribbon
Private Function GetChildControls(Group As RibbonGroup) As IEnumerable(Of RibbonControl)
Dim ChildControls As New List(Of RibbonControl)
Dim SubControls As IEnumerable(Of RibbonControl) = Group.Items
ChildControls.AddRange(SubControls)
' ...
' Some recursive call over SubControls to get the children of each child (not relevant here)
' ...
Return ChildControls
End Function
Code breaks at ChildControls.AddRange(SubControls), with the following exception:
System.InvalidCastException: 'Unable to cast object of type Microsoft.Office.Tools.Ribbon.RibbonControl[]' to type Microsoft.Office.Tools.Ribbon.RibbonControlImpl[]'.'
I cannot find any reference at all on RibbonControlImpl. The Microsoft documentation is silent, and - surprisingly - so are Google or StackOverflow.
Changing ChildControls.AddRange(SubControls) into SubControls.ToList.ForEach(Sub(p) ChildControls.Add(p)) does not work either, but a classic For Each does the trick:
For Each MySubControl As RibbonControl In SubControls
ChildControls.Add(MySubControl)
Next
I would like to understand what is happening here? Is Impl a suffix to interface types to signify something? Maybe 'Impl' stands for 'Implementation'? I could not find any information on this either.
Just some thoughts, no idea if I am right; what do you think?
Office.Ribbon.RibbonControl is an interop interface, hence cannot be used as a generic type across assemblies. A guess would be that Microsoft implemented a non-interop RibbonControlImp wrapper to which RibbonControl is implicitly cast every time it is referenced as a generic type.
No idea how this would be achieved, but that would explain why For Each ... Next does not throw the error, whilst relying on generic collections does.
I have inheritance structure: Foo implements IGraphNode inherits IGraphItem.
Foo, IGraphItem/IGraphNode, and the implementation for IGraphItem/IGraphNode all reside in separate assemblies. I am using an inversion of control container, so the project I'm working in has a reference to the first two (Foo and IGraphItem/IGraphNode), but not the implementation of IGraphItem/IGraphNode. I also have Option Strict on as it is required for this project (turning if off didn't fix the problem). I'm using .NET 3.5.
I am passing a IGraphItem around and I have code that looks like this:
Public Sub ProcessItem(of IGraphItem)(item As IGraphItem)
If TypeOf item Is Foo Then
Dim f1 = CType(item, Foo) 'Compiler error
Dim f2 = DirectCast(item, Foo) 'Compiler error
'This is what I'm currently having to do. It works.
Dim f = CType(CType(item, IGraphNode), Foo)
'Do stuff
End If
End Sub
Any idea why I'm having to do this? I should add that TryCast works, but since we've just confirmed that item's type is Foo, I don't see why I can't DirectCast it. Shouldn't it just let me and throw an exception if I'm wrong? Is there a better way to accomplish what I'm trying to do?
Your original code compiles without a problem, even when target framework is 3.5.
The problem with your current code is that you've defined a generic method whereas IGraphItem is not the type of your interface but the generic type T which can be any type. But it cannot be another type than T and you're trying to cast it to type Foo.
If you would change your method signature to anything else it would work, for instance:
Public Sub ProcessItem(of IGraphItm)(item As IGraphItem)
I assume that you're somehow "shadowing" the type IGraphItem of your interface with the generic type IGraphItem in this method.
It would also work if you would explicitely tell the compiler that item As IGraphItem actually is a item As YourNamespace.IGraphItem.
I'm sure Jon or Eric could explain it better, but maybe it's helpful anyway ;)
This article might answer your question. If not, well, it's an excellent reading anyway.
http://blogs.msdn.com/b/ericlippert/archive/2009/03/19/representation-and-identity.aspx
I have a simple code in C#:
Console.WriteLine(string.Join<char>("", ""));
And I can't convert it to VB.Net. Even reflector show me code in VB like:
Console.WriteLine(String.Join(Of Char)("", ""))
But it can't be compiled becouse I have an starge error:
Error 1 Expression expected.
It looks like VB.Net don't have this generic method at all.
Both project use Net Framework 4.
Why this error happened?
UPD:
I've create a custom class and copy Join(Of T) declaration to it:
Class string2
Public Shared Function Join(Of T)(ByVal separator As String, ByVal values As System.Collections.Generic.IEnumerable(Of T)) As String
Return "1"
End Function
End Class
Console.WriteLine(string2.Join(Of Char)("", ""))
It works
UPD2:
My compilation string, where you can see that I'm using Net4:
http://pastebin.com/TYgS3Ys3
Do you have a code element named String somewhere in your project?
Based on the answer you have added to this question (where you indicate that changing String to [String] appears to have solved the problem), I guessed that this may be the result of a naming collision.
I was able to duplicate the error you are seeing -- "Expression expected" -- by adding a module to my project called String and defining a (non-generic) Join method from within that module.
This may not be the specific scenario you find yourself in. But the fact that the code works for you with [String] is, to me, very compelling evidence of a simple namespace collision.
Based on the documentation for the "Expression expected" error, I'm guessing you haven't included the entire section of code where this error is appearing for you.
Do you have a lingering operator such as + or = somewhere?
(The VB.NET code you posted is indeed equivalent to the C# code above it and should compile no problem. This is why I suspect the real issue lies elsewhere.)
String.Join<T>(string, IEnumerable<T>) is useful with LINQ, for standard joins is better to use the String.Join(string, string()) overload.
In C#, "" as Char produces an empty Char (\0). Writing the same thing ("") in VB produces an empty string which is not the same as an empty char. In order to produce an empty character, you'll have to write New Char().
Your VB code therefore becomes:
Console.WriteLine(String.Join(Of Char)(New Char(), New Char()))
Edit
I just checked and it appears String.Join does not support the format you're specifying.
Instead, it goes as follows:
Join(separator As String, value As String()) As String
Your code should be as follows:
Console.WriteLine(String.Join("", New String() {""}))
String.Join(Of Char)(str1, str2) wasn't added til .net 4, it seems. That's why your custom class worked -- it had the declaration, but the String class in the framework you're actually using doesn't.
Check your settings and references to make sure you're targeting .net 4 all around -- cause that's the only thing that seems able at this point to stop the call from working.
Here the solution:
Console.WriteLine([String].Join(Of Char)("", ""))
Why this problem occurs only with generic method? I wish I know...
So what does this mean and how do I fix it?
This message occurs if I place the New keyword in the line(s) below. If I remove it, i get an error at runtime saying I need to use New. What am I doing wrong?
Dim oPS As AeccPointStyle = New AeccPointStyle
ops = oDescKey.PointStyle
Debug.Print(oPS.Name)
Debug.Print(oPS.MarkerSymbolName)
Also tried
Dim oPS As New AeccPointStyle
ops = oDescKey.PointStyle
Debug.Print(oPS.Name)
Debug.Print(oPS.MarkerSymbolName)
Thanks!
Update 1 - based on comment from Meta-Knight
1 -
Dim oPS As AeccPointStyle = Nothing
oPS = oDescKey.PointStyle
2 -
Dim oPS As AeccPointStyle = oDescKey.PointStyle
Both versions throw NullReferenceExceptions.
The empty constructor of AeccPointStyle is marked as friend, which means only classes inside its assembly can call it.
But looking at your code, I don't think you need to call New. Just set it to Nothing at first. Or even better, directly set your variable with the good value:
Dim oPS As AeccPointStyle = oDescKey.PointStyle
Edit about your NullReferenceException:
Typically, this type of exception is raised when you call a property of an object with a value of Nothing. In this case, if oDescKey was set to Nothing, such an exception would be raised.
If oDescKey does NOT have a value of Nothing, then the only thing that executes some code is the PointStyle property. So it's safe to assume that the PointStyle property throws a NullReferenceException. Try watching the oDescKey.PointStyle variable in the debugger, you should see that it throws an exception.
If your AeccPointStyle class is using a 'Friend' modifier,
ie it is defined as:
Friend Class AeccPointStyle
or the default constructor has the 'Friend' modifier,
ie:
Friend Sub New()
and the code you posted is not in the same assembly, you cannot call the constructor on this class. In order to get this to work, you must put your code in the same assembly as the AeccPointStyle class. Check out this page to learn more about the modifiers: more information about modifiers
My guess is the following: AeccPointStyle is declared in another assembly than the code sample in your question. The constructor (Sub New) of AeccPointStyle is declared a Friend, which means that it is reachable only within the same assembly.
You can solve this in two ways
Change Sub New so that it is Public
Provide a Shared Public Sub Create, that will create and return a new AeccPointStyle
AeccPointStyle doesn't have a public default constructor. The one you're trying to use is limited to other classes within the same assembly.
Here's some code I found online:
Dim oPointStyle As AeccPointStyle
Set oPointStyle = g_oAeccDoc.PointStyles.Add(strName)
Notice the PointStyles property (probably some sort of PointStylesColleciton) on g_oAeccDoc is instantiating and returning a new AeccPointStyle instance for you.
When using FRIEND as access modifier for your class, you need to make sure that both the class it-self and the class where you use it are in the same NAMESPACE, otherwise you will get this error message.
For other people encountering this issue, I had to do a one-way upgrade for an old project we were referencing. It upgraded it to .NET 4.0 as well, when it was 2.0/3.5. That caused the (also old) project that was an older version to get this error when referencing it. Changing the newly upgraded version back to .NET 3.5 did the trick for me. It's a very non-descript error!
I have a following code which works fine
MsgBox(AddSomething(Of String)("Hello", "World"))
Public Function AddSomething(Of T)(ByVal FirstValue As T, ByVal SecondValue As T) As String
Return FirstValue.ToString + SecondValue.ToString
End Function
Now we are redesigning the application to work with parameters of different types which will be provided through XML
<SomeValues>
<Add Param1="Somedata" Param2="SomeData" MyType="String"/>
<Add Param1="Somedata" Param2="SomeData" MyType="MyBusinessObject"/>
</SomeValues>
If I try to provide the following it gives error as Of accepts only type
''''Get DetailsFromXml --- MyType,Param1,Param2
MsgBox(AddSomething(Of Type.GetType(MyType))(Param1,Param2))
How to solve this issue.
Edit
The above example is given to make the question simple. Actual issue is as follows
I am using SCSF of P&P.
Following is per view code which has to be written for each view
Private Sub tsStudentTableMenuClick()
Dim _StudentTableListView As StudentListView
_StudentTableListView = ShowViewInWorkspace(Of StudentListView)("StudentTable List", WorkspaceNames.RightWorkspace)
_StudentTableListView.Show()
End Sub
Now I want to show the views dynamically.
Public Sub ShowModalView(ByVal ViewName As String)
Dim _MasterListView As >>>EmployeeListView<<<<
_MasterListView = ShowViewInWorkspace(Of >>>EmployeeListView<<<)("Employee List", WorkspaceNames.RightWorkspace)
_MasterListView.Show()
End Sub
So the part shown using the arrows above has to be somehow dynamically provided.
The point of generics is to provide extra information at compile-time. You've only got that information at execution-time.
As you're using VB, you may be able to get away with turning Option Strict off to achieve late binding. I don't know whether you can turn it off for just a small piece of code - that would be the ideal, really.
Otherwise, and if you really can't get the information at compile-time, you'll need to call it with reflection - fetch the generic "blueprint" of the method, call MethodInfo.MakeGenericMethod and then invoke it.
I assume that the real method is somewhat more complicated? After all, you can call ToString() on anything...
(It's possible that with .NET 4.0 you'll have more options. You could certainly use dynamic in C# 4.0, and I believe that VB10 will provide the same sort of functionality.)
In .Net generics, you must be able to resolve to a specific type at compile time, so that it can generate appropriate code. Any time you're using reflection, you're resolving the type at run time.
In this case, you're always just calling the .ToString() method. If that's really all your code does, you could just change the parameter type to Object rather than use a generic method. If it's a little more complicated, you could also try requiring your parameters to implement some common interface that you will define.
If all you are doing is ToString, then making the parameters object instead would solve the problem in the simplest way. Otherwise you are going to have to bind the type at run-time, which in C# looks like:
System.Reflection.MethodInfo mi = GetType().GetMethod("AddSomething");
mi = mi.MakeGenericMethod(Type.GetType(MyType));
object result = mi.Invoke(this, new object[] { Param1, Param2 });
Because it involves reflection it won't be fast though... but I assume that's not a problem in this context.