Calling a method / interface - c#

From Visual Studio I imported a WSDL via the Service References tool. From the methodsin the WSDL I need to call a method GetSessionID. The method is part of an Interface IdoSession. When I try to reference it in C# the compiler keeps telling me I am doing it wrong. What would be the correct syntax to call the GetSessionID method?
If I use this code
SSISSoapTester.IdoSession.IdoSession getID;
idResponse = getID.GetSessionID(idRequest);
The compiler tells me "Use of unassigned local varible 'getID'
If I use this code
SSISSoapTester.IdoSession.IdoSession getID;
getID = new SSISSoapTester.IdoSession.IdoSession();
idResponse = getID.GetSessionID(idRequest);
The compiler tells me "Cannot create an instance of the abstract calls or interface"
Granted this error makes sense to me because an interface is not a class.

It is hard to tell based on what you posted (please post actual code in the future), but I am guess ing that IdoSessionClient implements the IdoSession interface, which is what you have selected in your screenshot. In that case, you probably want to do something similar to:
GetSessionIdRequest request = new GetSessionIdRequest();
IdoSession client = new IdoSessionClient();
client.GetSessionId(request);

Related

C# - Make a new class not part of System.Object

I have a huge code base and I recently made a change where I changed the type of a parameter from String to a custom class. On the next compile I got all the areas where the impact was, but areas where the input type was of type Object failed. for e.g.
String str = "32"
int i = Convert.ToInt32(str)
Now I have changed String to a new custom type lets say MyCustomClass I would now want following code to fail on next compile
MyCustomClass str = new MyCustomClass("32")
int i = Convert.ToInt32(str)
but it won't as Convert.ToInt32 also accepts type Object. Is there some way I can make a change in MyCustomClass that it's not considered Object anymore.
Please note: Convert.ToInt32 is only used for sample I have many more such functions, so please focus your suggestion/answer to question asked.
Override ToString() and IConvertible
You said in the comments that your intentions are to find places where your object, which had previously been treated as a string, and are now being treated as an object.
In these situations typically, the third-party code would call .ToString() on your object to get something which it can use.
So, Convert.ToInt32(str) is equivalent to Convert.ToInt32(str.ToString()).
If you implement ToString() and IConvertible to return whatever your old version of str looked like then it should continue to work in the same way as the old version.
Probably.
Sorry I know that is not the 100% perfect compile time answer you were looking for, but I think you also know very well that your MyCustomClass will always be considered object.
Possible compile time answer:
Write a tool which uses reflection to iterate over every class/struct/interface in every system/third-party DLL.
Output a load of CS files which contain all these same classes, but just throw NotImplementedException.
(T4 could help you do this)
Compile these classes into dummy.dll
Your .csproj now references only this one dummy.dll, instead of the real dlls.
Your project should compile fine against the dummy dll.
Look at your dummy.cs files and delete any use of object.
Re-compile... and suddenly you get a load of compile time errors showing you anywhere you are using an object.
Impliment an implicit cast from MyCustomClass to String.
public static implicit operator string(MyCustomClass str)
{
return "Legacy respresentation of str";
}
This allows the complier the choice of choosing ToInt32(Object) or ToInt32(String), and I bet it favours the later.
This way all your existing function calls will remain the same so you wont have to be concerned about third party implentation details.
(Sorry, I am not at a computer right now so I can`t test that my assumtion is correct. If you do test this, be sure to consider extension methods, as they can affect the conpilers desision making in unexpected ways)

Visual Studio states that there is an ambiguous call, when there's only a single method with the given name

I am trying to figure out why this is happening, but I can't. I have a WCF service and inside it I created a class, called ExtensionUtil which will consist of extension methods only.
For now the only method I have in the ExntensionUtil class is called AddWithNullableValue. It looks like this:
public static void AddWithNullableValue(this SqlParameterCollection paramCollection, string paramName, object value)
{
SqlParameter param = new SqlParameter();
param.ParameterName = paramName;
param.Value = value == null ? DBNull.Value : value;
paramCollection.Add(param);
}
I am using this method in the DAL like this:
sqlCommand.Parameters.AddWithNullableValue("#categoryId", publication.CategoryId);
Everything compiles fine. However, when I try to start the service a compilation error occurs, stating:
The call is ambiguous between the following methods or properties:
'App_Code.Util.ExtensionUtil.AddWithNullableValue(System.Data.SqlClient.SqlParameterCollection, string, object)' and
'App_Code.Util.ExtensionUtil.AddWithNullableValue(System.Data.SqlClient.SqlParameterCollection, string, object)'
Why is this happening? I have only one method with this name and the compiler says that the call is ambiguous.
Edit:
When I remove the 'this' keyword in front of the SqlParameterCollection paramater, making the method an ordinary static method, instead of an extension one, everything works okay. Moreover, I looked in the entire solution (using Ctrl+Shift+F) for all occurraces of the 'AddWithNullableValues' keyword and the search resulted in the following: the signature of the method and the two places in my code where I call it. I then even created a completely new static class, added the same method with a completely different name and the same body and I still got the same error when I called it, so the problem must be something else.
Finally, I needed another extension method and when I called it in my code I got the same error for it.
public static Nullable<T> GetNullableValue<T>(this SqlDataReader sqlDataReader, string columnName) where T : struct
{
int columnIndex = sqlDataReader.GetOrdinal(columnName);
Nullable<T> value = null;
if (!sqlDataReader.IsDBNull(columnIndex))
{
value = (Nullable<T>)sqlDataReader.GetValue(columnIndex);
}
return value;
}
It seems to me that the solution has some problem with the extension methods and I don't know why. I built it successfully a couple of times, tried to clean it - everything works okay, until I try to use an extension method as an extension method, not as a static method.
Something similar happened to me when Visual Studio referenced a project to itself (no clue why). I was able to solve it be simply removing the nonsensical reference.
I found the solution to this problem and it worked for me. It's quite disturbing but you can read the complete answer here.
App_Code is not supported in a WAP. The App_Code folder is compiled at run-time; all code in a WAP is compiled at compile / development time. So, when you add an App_Code folder to a WAP. you end up with duplicate code; for example, a class defined in App_Code will also show up in the wap DLL. The fix is easy: just name the folder something else like Classes or CodeFiles.
By the way, thanks to all of you who tried to help me :)
The error message shows you have 2 methods with the same name and signature.
You need to either call it from the specific class or give them different namespaces. The caller is confused on which extension method you are trying to use and I believe the next version of C# will allow you to specify a namespace when calling an extension method.
If one of those does not actually exist anymore, then make sure you clean and build again to try and get rid of any leftovers.

Call to LotusSession.GetDatabase works in VB but not in C#

I have some old VB code to send mails using Lotus Notes that works, I have re-written it into C#, but it behaves differently:
VB:
NotesSession = CreateObject("Notes.Notessession")
NotesDb = NotesSession.GetDatabase("", "")
C#:
_notesSession = new NotesSession();
_notesSession.Initialize(passwordString);
_notesDatabase = _notesSession.GetDatabase( "", "");
First of in C# I need to Initialize the NotesSession with a password, and secondly it will not accept empty string parameters at runtime. Exception is thrown: "A database name must be provided".
In both VB and C# I refer to the same COM : Lotus Domino Objects
I need to be able to call the GetDatabase without specifying the server and database file.
Thanks in advance.
Solution (Thanks guys):
dynamic _notesSession = Activator.CreateInstance(Type.GetTypeFromProgID("Notes.NotesSession"));
_notesDatabase = _notesSession.GetDatabase("", "");
This way you have no intellisense but all properties and methods can be found here
When you create a new instance of the NoteSession type in C# using the new keyword, it will use the COM-interop dll that was referenced by the project at build-time. That is not exactly the same thing as calling CreateObject, which requires no interop dll. The closer equivalent in C# would be:
Type t = Type.GetTypeFromProgID("Notes.Notessession");
_notesSession = Activator.CreateInstance(t);
Or, if you really need to do the exact same thing, you could always add a reference to the Microsoft.VisualBasic.dll library and then call the Microsoft.VisualBasic.Interaction.CreateObject method from C#.
As Richard pointed out in the comments below, the likely reason why you are seeing a difference in behavior is because you are creating two different types of objects. Presumably, when you call new NotesSession in C#, it is using the NotesSession class from the Lotus namespace, rather than the one in the Notes namespace.

Instantiating a class - No overload for method 'Subjects' takes '0' arguments

I have referenced a dll in a asp.net 2.0 web site developed in Visual Studio. The person who supplied the dll said to reference it and instantiate a class called Subjects.
I have referenced it and if I type:
Subjects mySubjects = new Subjects();
it appears to be 'found' as 'Subjects' appears in light blue text.
If I then try to access a method by writing this:
string ProjectSubject = mySubjects.GetSubject(ProjectID);
again, it seems to be 'found' in that intellisense, as soon as you type the full stop after mySubjects shows the methods available to be called.
So far, so good. But, when I try to run the page, I get a compile error which is:
No overload for method 'Subjects' takes 0 arguments.
I don't understand. I thought you always had to reference a class with
someClass myClass = new someClass();
No overload for method 'Subjects' takes 0 arguments.
This means that there is no parameterless constructor defined for Subjects. Intellisense should show you the possible options when you type the initial opening parenthesis, otherwise look up the class in object browser to see the possible constructors (there could be more than 1).
It is also possible that there is no public constructor defined on that class, however this is unlikely as the author has told you to "instantiate an instance of Subjects". Again, object browser should tell you what's available.
Apparently the constructor for Subjects takes a parameter.
I obviously don't know if you have any sort of documentation for your assembly or not.
But you should be able to Visual Studio's 'Object Browser' feature to inspect the type, and from there perhaps figure out what type of parameter it takes.

Uses for [Obsolete(string, bool)] attribute for .NET

Note: I already checked msdn, it doesn't address my actual question, see below.
I'm trying to use the obsolete attribute on a (obviously obsolete) constructor in one of my classes. Here's the scenario:
I want to be able to force the developer to update to the new constructor without affecting already existing and deployed code. This way I can deploy my code to production just fine, but from a developers perspective, whenever they go into their code, instead of just getting a "warning" which I'm sure they'll just ignore, I want them to get a compile error because the status quo is no longer ok.
So my question is, will this affect only developers, or all calling apps, or do I have the whole thing wrong?
sample code:
public class MyClass
{
private string _userID; //new code
[Obsolete("This constructor is obsolete, please use other constructor.", true)]
public MyClass()
{
_userID = ""; //defaulting to empty string for all those using this constructor
}
public MyClass(string userID)
{
_userID = userID; //this is why they need to use this constructor
}
}
Any and all help will be appreciated, thanks in advance!
Yes, this primarily affects the compiler - any pre-built code won't be affected... unless that code explicitly checks for this attribute. For example, some serialization code (XmlSerializer, IIRC) checks for this - so it might not be entirely side-effect free... but in principal existing code won't usually be affected until they try to compile next.
Of course, if you are using this code from something that uses dynamic compilation (for example ASP.NET without pre-compile) then all bets are off.
The attribute is only an instruction to the compiler. Already existing binaries can still use the constructor.
So my question is, will this affect only developers, or all calling apps, or do I have the whole thing wrong?
This will only be used at compile time, by the compiler. It will not affect applications which have already been deployed.
As such, this will have the behavior you are trying to accomplish.
This is what [Obsolete] already does, no extra help is needed. It is not a compile time warning, it generates an error:
error CS0619: 'ConsoleApplication1.MyClass.MyClass()' is obsolete:
'This constructor is obsolete, please use other constructor.'

Categories