Best vb.net questions in August 2011

Mixing C# and VB.NET projects = broken "Go to definition"

11 votes

I have a large-ish solution, with C# and VB.NET projects mixed. Whenever I try to “Go to definition” on a class, property or method that’s defined in the other language, Visual Studio just takes me to the Object Browser, which is pretty annoying. Same for debugging: I can’t step into a project that's written in the other language.

Is there a way to fix this?

See this seems like a reported bug

Find all references / go to definition do not work across VB/C# in same solution.

Quote:

The project-to-project reference between a C# and VB project is treated like a file assembly reference where all symbols are treated as if coming from metadata.

What's the fastest WinForms controls suite (commercial)

10 votes

My employer wants to sell "sexy" applications which means they don't really want the standard controls of Windows to be used. I do, because of the better performance, but they pay so they decide. Currently I'm using the latest version of Telerik WinForms. They all may look great but the performance is very very disappointing ...

F.e.: I created just a simple empty WinForm project with just one Form without anything else (no controls added and no code). Without Telerik it takes < 1 second to load; with Telerik it takes 3-4 seconds, and I have a modern/fast PC ...

To be clear: it's not only the initial loading that's slow. The overall performance is also slower than I desire.

I know that using fancy controls means you have to sacrifice speed. But so much?

So, my question is: are there any (commercial) control packages that perform better? This is what it must provide at least:

  • Office 2007 look (colors and form).
  • Ribbon.
  • Docking control.

NB: Price must be around the same price as Telerik (< $900).

Update: sorry to see my question closed as being not constructive/suitable. Don't agree with it as I see the perfomance issue as a problem that could be solved by a better controls suite.

Have a look at the Krypton controls, they are very pretty and have excellent constancy through out.

Dynamic form creation in asp.net c#

7 votes

So, I need some input refactoring an asp.net (c#) application that is basically a framework for creating dynamic forms (any forms). From a high level point of view, there is a table that has the forms, and then there is a table that has all the form fields, where it is one to many between the two. There is a validation table, where each field can have multiple types of validation, and it is a one to many from the form fields table to the validation table.

So the issue is that this application has been sold as the be-all-end-all customizable solution to all the clients. So, the idea is whatever form they want, we can build it jsut using DB configurations. The thing is, that is not always possible, because there is complex relationship between the fields, and complex relationship between the forms themselves. Also, there is only once codebase, and this is for multiple clients - all of whom host it on their own. There is very specific logic for each of the clients, and they are ALL in the same codebase, with no real separation. Sometimes it was too difficult to make it generic, so there are instances where it has hard coded logic (as in if formID = XXX then do _). You can also have nested forms, as in, one set of fields on its own within each form.

So usually, when one client requests a change, we make the change and deploy it to that client - but then another client requests a different change, and we make the change and deploy it for THAT client, but the change from the earlier client breaks it, and its a headache trying to debug, because EVERYTHING is dynamic. There is no way we can rollback the earlier change, because then the other client would be screwed.

Its not done in a real 3-tier architecture - its a web site with references to a DB class, and a class library. There is business logic in the web site itself, in the class library, and the database stored procs (Validation is done in the stored procs).

I've been put in charge of re-organizing the whole thing, and these are my thoughts/questions:

  1. I think this is a bad model in general, because one of the things I heard one of the developers say is that anytime any client makes a change, we should deploy to everybody - but that is not realistic, if we have say 20 clients - there will need to be regression testing on EVERYTHING, since we don't know the impact...

  2. There are about 100 forms in total, and their is some similarity in them (not much). But I think the idea that a dynamic engine can solve ALL form requests was not realistic as well. Clients come up with the most weird requests. For example, they have this engine doing a regular data entry form AND a search form.

  3. There is a lot of preserving state between pages, and it is all done using session variables, which is ok, except that it is not really tracked, and so sessions from the same user keep getting overwritten, and I think sessions should be got rid of.

  4. Should I really just rewrite the whole thing? This app is about 3 years old, and there has been lots of testing and things done, and serious business logic implemented, so I hate to get rid of all that (joel's advice). But its really a mess of a sphagetti code, and everything takes forever to do, and things break all the time because of minor changes.

I've been reading Martin Fowlers "Refactoring" and Michael Feathers "working effectively with legacy code" - and they are good, but I feel they were written for an application that was 'slightly' better architected, where it is still a 3-tiered architecture, and there is 'some' resemblance of logic..

Thoughts/input anyone?

Oh, and "Help!"

My current project sounds like almost exactly the same product you're describing. Fortunately, I learned most of my hardest lessons on a former product, and so I was able to start my current project with a clean slate. You should probably read through my answer to this question, which describes my experiences, and the lessons I learned.

The main thing to focus on is the idea that you are building a product. If you can't find a way to implement a particular feature using your current product feature set, you need to spend some additional time thinking about how you could turn this custom one-off feature into a configurable feature that can benefit all (or at least many) of your clients.

So:

  1. If you're referring to the model of being able to create a fully customizable form that makes client-specific code almost unnecessary, that model is perfectly valid and I have a maintainable working product with real, paying clients that can prove it. Regression testing is performed on specific features and configuration combinations, rather than a specific client implementation. The key pieces that make this possible are:
    1. An administrative interface that is effective at disallowing problematic combinations of configuration options.
    2. A rules engine that allows certain actions in the system to invoke customizable triggers and cause other actions to happen.
    3. An Integration framework that allows data to be pulled from a variety of sources and pushed to a variety of sources in a configurable manner.
    4. The option to inject custom code as a plugin when absolutely necessary.
  2. Yes, clients come up with weird requests. It's usually worthwhile to suggest alternative solutions that will still solve the client's problem while still allowing your product to be robust and configurable for other clients. Sometimes you just have to push back. Other times you'll have to do what they say, but use wise architectural practices to minimize the impact this could have on other client code.
  3. Minimize use of the session to track state. Each page should have enough information on it to track the current page's state. Information that needs to persist even if the user clicks "Back" and starts doing something else should be stored in a database. I have found it useful, however, to keep a sort of breadcrumb tree on the session, to track how users got to a specific place and where to take them back to when they finish. But the ID of the node they're actually on currently needs to be persisted on a page-by-page basis, and sent back with each request, so weird things don't happen when the user is browsing to different pages in different tabs.
  4. Use incremental refactoring. You may end up re-writing the whole thing twice by the time you're done, or you may never really "finish" the refactoring. But in the meantime, everything will still work, and you'll have new features every so often. As a rule, rewriting the whole thing will take you several times as long as you think it will, so don't try to take the whole thing in a single bite.

.net .ToTitleCase not working on all upper case string

6 votes
   Public Function TitleCase(ByVal strIn As String)
          Dim result As String = ""
          Dim culture As New CultureInfo("en", False)
          Dim tInfo As TextInfo = culture.TextInfo()
          result = tInfo.ToTitleCase(strIn)
          Return result
     End Function

If I input "TEST" into the function above. The output is "TEST". Ideally it would output "Test"

I also tried the code snippets from this post to no avail: Use of ToTitleCase

Thanks in advance!

If memory serves, ToTitleCase() never seemed to work for all capitalized strings. It basically requires you to convert the string to lowercase prior to processing.

From the MSDN:

Generally, title casing converts the first character of a word to uppercase and the rest of the characters to lowercase. However, this method does not currently provide proper casing to convert a word that is entirely uppercase, such as an acronym.

Workaround Usage (in C#):

string yourString = "TEST";

TextInfo formatter = new CultureInfo("en-US", false).TextInfo;    
formatter.ToTitleCase(yourString.ToLower());

VB.Net Identical Case Condition

5 votes

I am converting some vb.net code to c# - as I am more comfortable with it and it helps me in resolving issues faster. However, I came across this code which is NOT an error in vb.net - but converting it to C# is generating a compiler error.

VB.Net Code

Select Case name
Case "FSTF"
    .....
Case "FSTF"
    .....
End Select

C# Converted Code

switch{
 case "FSTF": 
    ....;
    break;
 case "FSTF":
    ....;
    break;
}

and the error is:

The Label 'case "FSTF":' already occurs in this switch statement.

What is the solution here - does it mean that in the VB.Net code, the second case statement was just dummy - or was the first case dummy ??

Thanks

From the documentation for Select...Case:

If testexpression matches an expressionlist clause in more than one Case clause, only the statements following the first match run.

So here the second case is effectively redundant. Personally I prefer the C# approach of highlighting what was almost certainly an unnoticed programming error rather than the deliberate introduction of a duplicate case...

Problem Unit Testing in VB.NET

5 votes

I have the following code:

<TestMethod()> _
Public Sub GetDirectoryEntryTest()
    Dim path As String = runner.getLDAPPath()
    Dim expected As DirectoryEntry = runner.GetDirectoryEntry()
    Dim actual As DirectoryEntry
    actual = LDAPBase.GetDirectoryEntry(path)
    Assert.AreEqual(expected, actual)
End Sub

This unit test fails. The DirectoryEntry objects are exactly the same, but different references to different objects. I come from a Java background where you always have the .equals().

What can I do so that this will evaluate correctly and return true since for all intents and purposes, the objects are equal. Is there something I can do like I would do in Java and override the equals()?

Try comparing the paths of the objects with something like this:

Assert.AreEqual(expected.Path, actual.Path)

That will compare the underlying paths (string type) rather than the object references. If the paths being the same is enough you shouldn't have to override anything.

EDIT:

DirectoryEntry is a reference type that inherits Equals from Object and so:

From Object.Equals Method:

The default implementation of Equals supports reference equality for reference types, and bitwise equality for value types. Reference equality means the object references that are compared refer to the same object. Bitwise equality means the objects that are compared have the same binary representation.

Generated IL differences for VB.NET and C#

5 votes

Today I was playing around with Entity Framework and I've read that the generated IL for C# was different than VB.NET for the following code:

VB.NET:

Dim ctx As New TravelEntities

Sub Main()
    CallContext()
    CallContext()
    CallContext()
End Sub

Private Sub CallContext()

    Dim someCustomer = From x In ctx.Customer
            Where x.CustomerId.Equals(5)
            Select x
    Console.WriteLine(someCustomer.Count())
End Sub

C#:

    private static TravelEntities ctx = new TravelEntities();

    static void Main(string[] args)
    {
        CallContext(); 
        CallContext(); 
        CallContext();
    }

    private static void CallContext()
    {
        var someCustomer = from x in ctx.Customer
                           where x.CustomerId.Equals(5)
                           select x;
        Console.WriteLine(someCustomer.Count());
    }

They produce the following IL:

VB:

.method private static void  CallContext() cil managed
{
  // Code size       195 (0xc3)
  .maxstack  7
  .locals init ([0] class [System.Core]System.Linq.IQueryable`1<class VB_IL_Difference.Customer> someCustomer,
           [1] class [System.Core]System.Linq.Expressions.ParameterExpression VB$t_ref$S0,
           [2] class [System.Core]System.Linq.Expressions.Expression[] VB$t_array$S0,
           [3] class [System.Core]System.Linq.Expressions.ParameterExpression[] VB$t_array$S1,
           [4] class [System.Core]System.Linq.Expressions.ParameterExpression VB$t_ref$S1,
           [5] class [System.Core]System.Linq.Expressions.ParameterExpression[] VB$t_array$S2)
  IL_0000:  nop
  IL_0001:  ldsfld     class VB_IL_Difference.TravelEntities VB_IL_Difference.Module1::ctx
  IL_0006:  callvirt   instance class [System.Data.Entity]System.Data.Objects.ObjectSet`1<class VB_IL_Difference.Customer> VB_IL_Difference.TravelEntities::get_Customer()
  IL_000b:  ldtoken    VB_IL_Difference.Customer
  IL_0010:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
  IL_0015:  ldstr      "x"
  IL_001a:  call       class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
                                                                                                                                                 string)
  IL_001f:  stloc.1
  IL_0020:  ldloc.1
  IL_0021:  ldtoken    method instance int32 VB_IL_Difference.Customer::get_CustomerId()
  IL_0026:  call       class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle)
  IL_002b:  castclass  [mscorlib]System.Reflection.MethodInfo
  IL_0030:  call       class [System.Core]System.Linq.Expressions.MemberExpression [System.Core]System.Linq.Expressions.Expression::Property(class [System.Core]System.Linq.Expressions.Expression,
                                                                                                                                             class [mscorlib]System.Reflection.MethodInfo)
  IL_0035:  ldtoken    method instance bool [mscorlib]System.Int32::Equals(int32)
  IL_003a:  call       class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle)
  IL_003f:  castclass  [mscorlib]System.Reflection.MethodInfo
  IL_0044:  ldc.i4.1
  IL_0045:  newarr     [System.Core]System.Linq.Expressions.Expression
  IL_004a:  stloc.2
  IL_004b:  ldloc.2
  IL_004c:  ldc.i4.0
  IL_004d:  ldc.i4.5
  IL_004e:  box        [mscorlib]System.Int32
  IL_0053:  ldtoken    [mscorlib]System.Int32
  IL_0058:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
  IL_005d:  call       class [System.Core]System.Linq.Expressions.ConstantExpression [System.Core]System.Linq.Expressions.Expression::Constant(object,
                                                                                                                                               class [mscorlib]System.Type)
  IL_0062:  stelem.ref
  IL_0063:  nop
  IL_0064:  ldloc.2
  IL_0065:  call       class [System.Core]System.Linq.Expressions.MethodCallExpression [System.Core]System.Linq.Expressions.Expression::Call(class [System.Core]System.Linq.Expressions.Expression,
                                                                                                                                             class [mscorlib]System.Reflection.MethodInfo,
                                                                                                                                             class [System.Core]System.Linq.Expressions.Expression[])
  IL_006a:  ldc.i4.1
  IL_006b:  newarr     [System.Core]System.Linq.Expressions.ParameterExpression
  IL_0070:  stloc.3
  IL_0071:  ldloc.3
  IL_0072:  ldc.i4.0
  IL_0073:  ldloc.1
  IL_0074:  stelem.ref
  IL_0075:  nop
  IL_0076:  ldloc.3
  IL_0077:  call       class [System.Core]System.Linq.Expressions.Expression`1<!!0> [System.Core]System.Linq.Expressions.Expression::Lambda<class [mscorlib]System.Func`2<class VB_IL_Difference.Customer,bool>>(class [System.Core]System.Linq.Expressions.Expression,
                                                                                                                                                                                                                 class [System.Core]System.Linq.Expressions.ParameterExpression[])
  IL_007c:  call       class [System.Core]System.Linq.IQueryable`1<!!0> [System.Core]System.Linq.Queryable::Where<class VB_IL_Difference.Customer>(class [System.Core]System.Linq.IQueryable`1<!!0>,
                                                                                                                                                   class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`2<!!0,bool>>)
  IL_0081:  ldtoken    VB_IL_Difference.Customer
  IL_0086:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
  IL_008b:  ldstr      "x"
  IL_0090:  call       class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
                                                                                                                                                 string)
  IL_0095:  stloc.s    VB$t_ref$S1
  IL_0097:  ldloc.s    VB$t_ref$S1
  IL_0099:  ldc.i4.1
  IL_009a:  newarr     [System.Core]System.Linq.Expressions.ParameterExpression
  IL_009f:  stloc.s    VB$t_array$S2
  IL_00a1:  ldloc.s    VB$t_array$S2
  IL_00a3:  ldc.i4.0
  IL_00a4:  ldloc.s    VB$t_ref$S1
  IL_00a6:  stelem.ref
  IL_00a7:  nop
  IL_00a8:  ldloc.s    VB$t_array$S2
  IL_00aa:  call       class [System.Core]System.Linq.Expressions.Expression`1<!!0> [System.Core]System.Linq.Expressions.Expression::Lambda<class [mscorlib]System.Func`2<class VB_IL_Difference.Customer,class VB_IL_Difference.Customer>>(class [System.Core]System.Linq.Expressions.Expression,
                                                                                                                                                                                                                                            class [System.Core]System.Linq.Expressions.ParameterExpression[])
  IL_00af:  call       class [System.Core]System.Linq.IQueryable`1<!!1> [System.Core]System.Linq.Queryable::Select<class VB_IL_Difference.Customer,class VB_IL_Difference.Customer>(class [System.Core]System.Linq.IQueryable`1<!!0>,
                                                                                                                                                                                    class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`2<!!0,!!1>>)
  IL_00b4:  stloc.0
  IL_00b5:  ldloc.0
  IL_00b6:  call       int32 [System.Core]System.Linq.Queryable::Count<class VB_IL_Difference.Customer>(class [System.Core]System.Linq.IQueryable`1<!!0>)
  IL_00bb:  call       void [mscorlib]System.Console::WriteLine(int32)
  IL_00c0:  nop
  IL_00c1:  nop
  IL_00c2:  ret
} // end of method Module1::CallContext

C#:

    .method private hidebysig static void  CallContext() cil managed
{
  // Code size       141 (0x8d)
  .maxstack  7
  .locals init ([0] class [System.Core]System.Linq.IQueryable`1<class C_IL_Difference.Customer> someCustomer,
           [1] class [System.Core]System.Linq.Expressions.ParameterExpression CS$0$0000,
           [2] class [System.Core]System.Linq.Expressions.Expression[] CS$0$0001,
           [3] class [System.Core]System.Linq.Expressions.ParameterExpression[] CS$0$0002)
  IL_0000:  nop
  IL_0001:  ldsfld     class C_IL_Difference.TravelEntities C_IL_Difference.Program::ctx
  IL_0006:  callvirt   instance class [System.Data.Entity]System.Data.Objects.ObjectSet`1<class C_IL_Difference.Customer> C_IL_Difference.TravelEntities::get_Customer()
  IL_000b:  ldtoken    C_IL_Difference.Customer
  IL_0010:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
  IL_0015:  ldstr      "x"
  IL_001a:  call       class [System.Core]System.Linq.Expressions.ParameterExpression [System.Core]System.Linq.Expressions.Expression::Parameter(class [mscorlib]System.Type,
                                                                                                                                                 string)
  IL_001f:  stloc.1
  IL_0020:  ldloc.1
  IL_0021:  ldtoken    method instance int32 C_IL_Difference.Customer::get_CustomerId()
  IL_0026:  call       class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle)
  IL_002b:  castclass  [mscorlib]System.Reflection.MethodInfo
  IL_0030:  call       class [System.Core]System.Linq.Expressions.MemberExpression [System.Core]System.Linq.Expressions.Expression::Property(class [System.Core]System.Linq.Expressions.Expression,
                                                                                                                                             class [mscorlib]System.Reflection.MethodInfo)
  IL_0035:  ldtoken    method instance bool [mscorlib]System.Int32::Equals(int32)
  IL_003a:  call       class [mscorlib]System.Reflection.MethodBase [mscorlib]System.Reflection.MethodBase::GetMethodFromHandle(valuetype [mscorlib]System.RuntimeMethodHandle)
  IL_003f:  castclass  [mscorlib]System.Reflection.MethodInfo
  IL_0044:  ldc.i4.1
  IL_0045:  newarr     [System.Core]System.Linq.Expressions.Expression
  IL_004a:  stloc.2
  IL_004b:  ldloc.2
  IL_004c:  ldc.i4.0
  IL_004d:  ldc.i4.5
  IL_004e:  box        [mscorlib]System.Int32
  IL_0053:  ldtoken    [mscorlib]System.Int32
  IL_0058:  call       class [mscorlib]System.Type [mscorlib]System.Type::GetTypeFromHandle(valuetype [mscorlib]System.RuntimeTypeHandle)
  IL_005d:  call       class [System.Core]System.Linq.Expressions.ConstantExpression [System.Core]System.Linq.Expressions.Expression::Constant(object,
                                                                                                                                               class [mscorlib]System.Type)
  IL_0062:  stelem.ref
  IL_0063:  ldloc.2
  IL_0064:  call       class [System.Core]System.Linq.Expressions.MethodCallExpression [System.Core]System.Linq.Expressions.Expression::Call(class [System.Core]System.Linq.Expressions.Expression,
                                                                                                                                             class [mscorlib]System.Reflection.MethodInfo,
                                                                                                                                             class [System.Core]System.Linq.Expressions.Expression[])
  IL_0069:  ldc.i4.1
  IL_006a:  newarr     [System.Core]System.Linq.Expressions.ParameterExpression
  IL_006f:  stloc.3
  IL_0070:  ldloc.3
  IL_0071:  ldc.i4.0
  IL_0072:  ldloc.1
  IL_0073:  stelem.ref
  IL_0074:  ldloc.3
  IL_0075:  call       class [System.Core]System.Linq.Expressions.Expression`1<!!0> [System.Core]System.Linq.Expressions.Expression::Lambda<class [mscorlib]System.Func`2<class C_IL_Difference.Customer,bool>>(class [System.Core]System.Linq.Expressions.Expression,
                                                                                                                                                                                                                class [System.Core]System.Linq.Expressions.ParameterExpression[])
  IL_007a:  call       class [System.Core]System.Linq.IQueryable`1<!!0> [System.Core]System.Linq.Queryable::Where<class C_IL_Difference.Customer>(class [System.Core]System.Linq.IQueryable`1<!!0>,
                                                                                                                                                  class [System.Core]System.Linq.Expressions.Expression`1<class [mscorlib]System.Func`2<!!0,bool>>)
  IL_007f:  stloc.0
  IL_0080:  ldloc.0
  IL_0081:  call       int32 [System.Core]System.Linq.Queryable::Count<class C_IL_Difference.Customer>(class [System.Core]System.Linq.IQueryable`1<!!0>)
  IL_0086:  call       void [mscorlib]System.Console::WriteLine(int32)
  IL_008b:  nop
  IL_008c:  ret
} // end of method Program::CallContext

As it seems the VB.NET version of this code will contact the database every time the code is executed while the C# version will retrieve the entities from the cache when the code is executed multiple times.

Why would they make both languages behave in such a different manner? It was my misconception that both languages just differed in syntax and had almost exactly the same generated IL.

Are there any more examples where both languages generated such different IL?

Part of the differences you are seeing may be due to calling the end Select x. Since it is not required in the VB query syntax but you are explicitly declaring it, VB includes it in the compilation. You could have stated the VB syntax as follows just as easily:

Dim someCustomer = From x In ctx.Customer 
        Where x.CustomerId.Equals(5) 

Since C# requires the essentially no-oped Select clause at compile time, the compiler optimizes it out in the generated IL.

I suspect in this example, you would see greater differences between the generated expression trees between VB and C# if you used CustomerName =(=) "Foo" because C# and VB have very different handling of string equality. I've seen quite a few LINQ providers (including LINQ to Bing, LINQ to Twitter, EF Sample Query Provider, NOrm) that fail to evaute CustomerName = "Foo" in VB because they only tested their expression tree parsing in C#.

As for your claim that C# caches the results, I'm not seeing that using the following code against Northwind (using LinqPad). It is still calling the database 3 times.

void Main()          
{          
    CallContext();           
    CallContext();           
    CallContext();          
}          

private void CallContext()          
{          
    var someCustomer = from x in Customers          
                       where x.CustomerID.Equals("ALFKI")          
                       select x;          
    Console.WriteLine(someCustomer.Count());          
} 

Calling a .NET Function that requires a .NET type from Classic ASP

4 votes

Please Help me.I am trying to over come this paoblem from last 2 days But i am not able to overcome.

I was able to set up the environment so that I can call .NET method (via COM) from a classic ASP page.

Everything actually works as intended until when I have to call a .NET method that requires a .NET type.

So I have a method named SetTable Like Below

I have a function like this in .Net

Public Sub SetTable(ByVal _City As City, ByVal _Country As Country)
          'doing some thing
End Sub

and i have asp code like this:

dim CountryUtil, City, Country
set CountryUtil= Server.CreateObject("mydll.CountryUtil")
set City= Server.CreateObject("mydll.City")
set Country = Server.CreateObject("mydll.Country")
city.id= 123
city.property = "so and so"

Country.id= 123
Country.property = "so and so"

CountryUtil.SetTable(City, Country)

' I get this error here:

'Microsoft VBScript runtime error '800a0005' 'Invalid procedure call or argument: 'SetTable'

Thanks in advance.

in vbscript you only have variants so Country and City are just objects of type variant not of type Country or City.

you will have to change the .net method SetTable (or write a new one) which accepts "variants" (object) and then cast those objects to your .net City and Country objects.

How do I locate the last occurrence of string in a string?

4 votes

Is there a function which would search for the last occurrence of a certain substring and return the index of it?

For example, if I want to search for the last occurrence of the char '\' in a file path 'C:\Program Files\Microsoft'.

string.LastIndexOf

Dynamic loading working fine, except after the executable is ILMerged

4 votes

This is strange.

I have a windows application that dynamically loads DLLs using Reflection.Assembly.LoadFrom(dll_file_name_here).

It works as expected, until I ILMerge the application with another DLL.

So this scenario works fine:

  • MyApp.exe
  • MyAppComponent.dll
  • Plugin.dll

Once I ILMerge MyApp.exe and MyAppComponent.dll resulting in:

  • MyApp.exe
  • Plugin.dll

Calling Reflection.Assembly.LoadFrom("Plugin.dll") seems to load successfully, however once I try to do anything with it eg:

foreach ( typeAsm in Reflection.Assembly.LoadFrom("Plugin.dll")) 

I get an exception "unable to load one or more of the requested types. retrieve the loader exceptions property for more informtion".

The frustrating thing is I can't really debug it, because debugging pre merging works perfectly!

Help?

My guess is that Plugin.dll references MyApp.exe or MyAppComponent.dll, which are not binary compatible (MyApp.exe) or not there at all (MyApp.dll) after ILMerging.

If that is the case, you shouldn't ILMerge them.

Can't convert this into VB.net

4 votes

I'm trying to convert the following into vb.net. Thanks in advance

   Categories.DataSource = objDT.Rows.Cast<DataRow>()
        .Select(r => new { Attendee = r.Field<string>("Attendee"), Item = r.Field<string>("Item") })
        .GroupBy(v => v.Attendee)
        .Select(g => new { Attendee = g.Key, Item = g.ToList() });

This is where I get stuck, I have tried two different methods but still nothing works:

Categories.DataSource = objDT.AsEnumerable() _
    .Select(Function(r) New With {.Attendee = r.Field(Of String)("Attendee"), .Item = r.Field(Of String)("Item")}) _
    .GroupBy(Function(v) v.Field(Of String)("Attendee")) _
    .Select(Function(g) Attendee = g.Key)

or

Categories.DataSource = objDT.Rows.Cast(Of DataRow)().AsEnumerable _
    .Select New Object(){ Function(r As DataRow) Attendee = r.Field(Of String)("Attendee"), Item = r.Field(Of String)("Item")} _
.GroupBy( Function(v) v.Category) _
.Select( Function(g) new { Category = g.Key, Numbers = g.ToList() }

Try this :

  Categories.DataSource = objDT.Rows.Cast(Of DataRow)().Select(Function(r) New With { _
 .Attendee = r.Field(Of String)("Attendee"), _
 .Item = r.Field(Of String)("Item") _
}).GroupBy(Function(v) v.Attendee).Select(Function(g) New With { _
 .Attendee = g.Key, _
 .Item = g.ToList() _
})

Object Class (New Object() With {})is different than anonymous type (New With {}).

You can use this site in the future : http://www.developerfusion.com/tools/convert/csharp-to-vb/ . It works pretty well for most of the conversions.

C# translation to vb.net

4 votes

I tried to translate following c# code

public static class ObjectSetExtensions
{
    public static void AddObjects<T>(this ObjectSet<T> objectSet, IEnumerable<T> objects)
    {
         foreach (var item in objects)
         {
             objectSet.AddObject(item);
         }
    }
}

to vb.net

Module ObjectSetExtensions
    <System.Runtime.CompilerServices.Extension()>
    Public Sub AddObjects(Of T)(ByVal objectSet As ObjectSet(Of T), ByVal objects As IEnumerable(Of T))
        For Each item In objects
            objectSet.AddObject(item)
        Next
    End Sub
End Module

but I getting an error that says "Type argument 'T' does not satisfy the 'Class' constraint for type parameter 'TEntity'."

What I missing?

The C# version doesn't compile either, for the same reason. It should be:

public static void AddObjects<T>(this ObjectSet<T> objectSet,
                                 IEnumerable<T> objects)
    where T : class // Note this bit
{
     foreach (var item in objects)
     {
         objectSet.AddObject(item);
     }
}

And the VB version is:

<Extension> _
Public Sub AddObjects(Of T As Class)(ByVal objectSet As ObjectSet(Of T), _
                                     ByVal objects As IEnumerable(Of T))
    Dim local As T
    For Each local In objects
        objectSet.AddObject(local)
    Next
End Sub

Note how in the VB version the constraint is part of the type parameter declaration. For more details, see MSDN.

Calling a javascript function from a modal window in vb.net

4 votes

I want to calling a javascript function from a asp.net modal window using vb. The javascript function is to close the same modal window.

The function I want call is: function CloseModalWindow(winName)

I tried

Page.ClientScript.RegisterStartupScript  

but that does not work. How can I do that from vb.net code behind?

You're actually on the exact right track.

You should find that you are able to call the described method by using something like this...

ClientScript.RegisterStartupScript(Me.GetType, Guid.NewGuid().ToString(), "window.parent.CloseModalWindow('WindowName');", True)

Adding a keyword to VB.net? ("Exists" vs "IsNot Nothing")

4 votes

IsNot Nothing is very common, but it's a double negative =o

I'd like to use Exists instead. Is there someway I can add a keyword to my VB vocab?

For now, I wrote an extension that adds _Exists() as a property to each object. I use this frequently, but I'd still prefer an actual keyword.

<HideModuleName()>
Public Module CustomExtensions

    ''' <summary>
    ''' Returns <c>True</c> if [object] is not <c>Nothing</c>; otherwise <c>False</c>.
    ''' </summary>
    <System.Runtime.CompilerServices.Extension()>
    Public Function _Exists(obj As Object) As Boolean
        Return obj IsNot Nothing
    End Function

End Module

I use Visual Studio 2010 exclusively, so if I could trick VS into converting my custom phraseology into the standard syntax, that'd work for me.

Thanks!

This answer isn’t very helpful but here goes: currently, you cannot do this.

Future versions of VS (particularly when they release their compiler service internals and make them extensible) could allow it – although I actually doubt that they will allow new keywords to be added, as this isn’t in the interest of a compiler vendor who wants to ensure an ecosystem of compatible code.

VB.NET If (ternary) bug

4 votes

I found a simple bug in VB.NET that can be easily reproduced:

Dim pDate As Date?
Dim pString As String = ""

' works fine as expected
pDate = If(False, "", Nothing) 

' expected: pDate will be set to Nothing. 
' BUG: Conversion from string "" to type 'Date' is not valid.
pDate = If(False, pString, Nothing) 

'These both fail with the same error
pDate = pString
Dim pDate2 As Date? = "" 

Question: Is this a bug? Or is there something wrong with me or my PC? If this is a bug, is there a bug report of this (I cant seem to find it)?

Lessons learned:

  1. this is not a bug
  2. nullable date accepts object nothing
  3. nullable date rejects string nothing

pDate = Nothing ' ok. nullable date accepts object nothing
pString = Nothing
pDate = pString ' error. nullable date rejects string nothing

The bug is in your first use of If(), not the second. Contrary to your comment, the result there is not "expected". That call should fail, because "" cannot convert to a date and the ternary operator is typesafe at all levels whether or not the expression is used.

I suspect it succeeds because of a compiler optimization: since everything is all literals, the condition is optimized away. It's harder to make the optimization the second time, because the pString variable might be changed by another thread the compiler doesn't know about yet.

Someone who's handier with IL can probably confirm this.

The real surprise for me is that this is not caught until runtime. I would expect the compiler to notice the type mismatch and complain at that level, rather than waiting until execution. Your VB Option settings may have something to do with that.

Where is the main function in VB.Net

3 votes

I have taken over support of a VB.Net WinForms application. I am actually a c# developer and am more familiar with the setup of visual studio projects in c# projects. Now I am trying to determine why my application is crashing on a specific XP installation, and I read the suggestion here

http://social.msdn.microsoft.com/forums/en-US/winformssetup/thread/53c2de93-ab33-41d0-b5dd-7ca5fbfa5c24/

to add a try catch block in the main function. This is suggested in about the 5th post from the bottom. (I will quote it below) However, if I look in the VB.Net visual studio project, I do not find a Main() procedure. What I do find is a grey folder called "My project" with a "Application.myapp" file inside it. This file has an associated designer file, but if I click on it I see the following xml:

<?xml version="1.0" encoding="utf-8"?>
<MyApplicationData xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <MySubMain>true</MySubMain>
  <MainForm>MDIMain</MainForm>
  <SingleInstance>false</SingleInstance>
  <ShutdownMode>0</ShutdownMode>
  <EnableVisualStyles>true</EnableVisualStyles>
  <AuthenticationMode>0</AuthenticationMode>
  <SaveMySettingsOnExit>true</SaveMySettingsOnExit>
</MyApplicationData>

So can anyone enlighten me to where the actual main procedure call is for this VB.Net project so that I can try catch the exception that is occurring. If, as I suspect, there isn't actually a Main procedure in my VB.Net project, can someone maybe let me know how I can go about doing the following in my project:

[STAThread]
static void Main()
{
    try
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
    catch (System.IO.FileNotFoundException ex)
    {
        MessageBox.Show(ex.Message + "    \n\n\n" + ex.StackTrace);
    }
}

The more VB way to do this is to open the Application properties and click on the ViewApplicationEvents button. This will open the Application.xaml.vb file where you can add custom event handlers for the application. Select Application Events from the left drop-down and you can easily access a bunch of events including DispatcherUnhandledException, Activated, Navigating, Startup, Exit, etc. You can also add the Main method here by selecting Applciation from the left drop-down and selecting Main from the right drop down.

In the case of WindowsForms applications, the process is similar. However when you select the Applciation Events button, the file that is shown is the ApplicationEvents.vb file. In here, to add a global error handler, select the left drop-down and select MyApplication Events. Then in the right drop-down, add the UnhandledException handler. You can also create your Main method here as well.