Creating Generic Class from 2 classes

T

tshad

This is a little complicated to explain but I have some web services on a
machine that work great.

The problem is that I have run into a situation where I need to set up my
program to access one or another (could also be 3) different web servers to
use these Web Services. The Web Services are identical on all the machines.
I tried just changing the URL of the Web Services and cannot make it work.
I then decided to create 2 identical web services (one for each machine) and
then use a generic type to use in my code.

The 2 web Servers are Earth and Saturn.

I originally had a Web Service called RemoteUserService, which has a method
fetchRemoteUserInfo.

To make this work I created 2 web services and called them RemoteUserEarth
and RemoteUserSaturn. Both Services are identical except for the URL they
point to and their Namespaces (ClassLibrary4.RemoteUserEarth and
ClassLibrary4.RemoteUserEarth).

I then tried all combinations of defines to make this work and kept coming
up with compiler errors - mainly "Cannot Implicitly assign" errors.

I came closest with:

ClassLibrary4.RemoteUserEarth.RemoteUserServiceService
remoteUserServiceEarth = new
ClassLibrary4.RemoteUserEarth.RemoteUserServiceService();

ClassLibrary4.RemoteUserSaturn.RemoteUserServiceService
remoteUserServiceSaturn = new
ClassLibrary4.RemoteUserSaturn.RemoteUserServiceService();

object remoteUserService;

remoteUserService =
(ClassLibrary4.RemoteUserSaturn.RemoteUserServiceService)remoteUserServiceTfs;

This compiles fine, but I can't use the remoteUserService in my code as it
is an object.

ruDataBean = remoteUserService.fetchRemoteUserInfo(
userID,
"swpays",
"10.0.0.25",
"C", //Client (employer)
sessionID);

This gives me an error "'object' does not contain a definition for
'fetchRemoteUserInfo'".

What I am trying to do is get remoteUserService be the generic class that I
can using throughout my code. I don't want to create multiple instances of
the same code when the only difference is the machine I point to. If I then
have to set up a 3rd machine, I would have recreate all my code again for
the 3rd machine. I would much rather just set up another variable, such as
remoteUserServiceMars which I just assign to remoteUserService when I point
to that machine.

Can this be done?

Thanks,

Tom
 
V

Vijay

Tshad,

Changing URL to connect to different webservices is the best and easy way..I
do it all the time and it works great, we connect to different servers
also.. Could you post a sample of your problem in ability to connect to
different URL.

Vijay
 
T

tshad

Vijay said:
Tshad,

Changing URL to connect to different webservices is the best and easy
way..I do it all the time and it works great, we connect to different
servers also.. Could you post a sample of your problem in ability to
connect to different URL.

I tried that using the following:

remoteUserService.Url =
http://10.0.0.25:8080/data/services/RemoteUserService;

newHireService.Url = http://10.0.0.25:8080/data/services/newHireService;

employeeTaxService.Url =
http://10.0.0.25:8080/data/services/employeeTaxService;

This worked for the first one, but not the second one. These were written
in Java, and we do have a problem with creating the proxy when using
multi-dimensional strings ([][]).

I don't know if this is the case, but what I am trying to do is just create
all the web service Object and then create generic object that I change to
whichever service I need to access.

I just know how to get this to work. I thought I had it finally setting up
the generic service as an object and I seem to be able to assign the actual
service to it, but I can't seem to access the methods (and I assume the
properties).

Is there a way to make this method work?

Thanks,

Tom
 
V

Vijay

The webservices that shipped with 1.1 or in parallel is what i am using...
There are certain datatypes that it will not understand.. like I can't send
a DataTable as a parameter, have to wrap it in a DataSet and send it...
Maybe the string[][] is a problem.. I have not tried that parameter.. if you
get a error when adding or creating object? what is the error message can
you post it?

Vijay

tshad said:
Vijay said:
Tshad,

Changing URL to connect to different webservices is the best and easy
way..I do it all the time and it works great, we connect to different
servers also.. Could you post a sample of your problem in ability to
connect to different URL.

I tried that using the following:

remoteUserService.Url =
http://10.0.0.25:8080/data/services/RemoteUserService;

newHireService.Url = http://10.0.0.25:8080/data/services/newHireService;

employeeTaxService.Url =
http://10.0.0.25:8080/data/services/employeeTaxService;

This worked for the first one, but not the second one. These were written
in Java, and we do have a problem with creating the proxy when using
multi-dimensional strings ([][]).

I don't know if this is the case, but what I am trying to do is just
create all the web service Object and then create generic object that I
change to whichever service I need to access.

I just know how to get this to work. I thought I had it finally setting
up the generic service as an object and I seem to be able to assign the
actual service to it, but I can't seem to access the methods (and I assume
the properties).

Is there a way to make this method work?

Thanks,

Tom
 
T

tshad

The webservices are created by another company that does our software to
access their functions. These are written in Java.

The error I get is (first line is the important one):
**********************************************************************************************************
System.InvalidOperationException: There is an error in XML document (43,
19). ---> System.InvalidCastException: Cannot assign object of type
System.String[][] to an object of type System.String[].
at
Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read3_RemoteUserDataBean()
at
System.Xml.Serialization.XmlSerializationReader.ReadReferencingElement(String
name, String ns, Boolean elementCanBeType, String& fixupReference)
at
System.Xml.Serialization.XmlSerializationReader.ReadReferencedElements()
at
Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read6_fetchRemoteUserInfoResponse()
--- End of inner exception stack trace ---
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader
xmlReader, String encodingStyle, XmlDeserializationEvents events)
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader
xmlReader, XmlDeserializationEvents events)
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader
xmlReader)
at
System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage
message, WebResponse response, Stream responseStream, Boolean asyncCall)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String
methodName, Object[] parameters)
at
ClassLibrary4.RemoteUser.RemoteUserServiceService.fetchRemoteUserInfo(String
in0, String in1, String in2, String in3, String in4)
at MyFunctions.NewHire.NewHireLogon(String sessionID)
at MyFunctions.NewHire..ctor()
at TestDll.Class1.Main(String[] args) in
c:\vsprojects\testdll\class1.cs:line 24
********************************************************************************************************************

This says I need to go into the Proxy (web reference.cs) code that VS
creates. Part of the code looks like:

********************************************************************************************
[System.Xml.Serialization.SoapTypeAttribute("RemoteUserDataBean",
"com.fwdco.wsbeans")]

public class RemoteUserDataBean{


/// <remarks/>

public string employeeId;


/// <remarks/>

public string[] employerList;


/// <remarks/>

public string ipAddress;


/// <remarks/>

public string password;


/// <remarks/>

public string peoContactEmail;


/// <remarks/>

public string userName;


/// <remarks/>

public string valid;

}

**********************************************************************************************

The problem is the emailList (in this case):

public string[] employerList;


it should be

public string[][] employerList;

Whenever I add one of these web services I have to find all these variables
and change them to make them work. You have to know which ones are
multi-dimensional as some are not and the [] is correct.

Tom

Vijay said:
The webservices that shipped with 1.1 or in parallel is what i am using...
There are certain datatypes that it will not understand.. like I can't
send a DataTable as a parameter, have to wrap it in a DataSet and send
it... Maybe the string[][] is a problem.. I have not tried that
parameter.. if you get a error when adding or creating object? what is the
error message can you post it?

Vijay

tshad said:
Vijay said:
Tshad,

Changing URL to connect to different webservices is the best and easy
way..I do it all the time and it works great, we connect to different
servers also.. Could you post a sample of your problem in ability to
connect to different URL.

I tried that using the following:

remoteUserService.Url =
http://10.0.0.25:8080/data/services/RemoteUserService;

newHireService.Url = http://10.0.0.25:8080/data/services/newHireService;

employeeTaxService.Url =
http://10.0.0.25:8080/data/services/employeeTaxService;

This worked for the first one, but not the second one. These were
written in Java, and we do have a problem with creating the proxy when
using multi-dimensional strings ([][]).

I don't know if this is the case, but what I am trying to do is just
create all the web service Object and then create generic object that I
change to whichever service I need to access.

I just know how to get this to work. I thought I had it finally setting
up the generic service as an object and I seem to be able to assign the
actual service to it, but I can't seem to access the methods (and I
assume the properties).

Is there a way to make this method work?

Thanks,

Tom
Vijay

This is a little complicated to explain but I have some web services on
a machine that work great.

The problem is that I have run into a situation where I need to set up
my program to access one or another (could also be 3) different web
servers to use these Web Services. The Web Services are identical on
all the machines. I tried just changing the URL of the Web Services and
cannot make it work. I then decided to create 2 identical web services
(one for each machine) and then use a generic type to use in my code.

The 2 web Servers are Earth and Saturn.

I originally had a Web Service called RemoteUserService, which has a
method fetchRemoteUserInfo.

To make this work I created 2 web services and called them
RemoteUserEarth and RemoteUserSaturn. Both Services are identical
except for the URL they point to and their Namespaces
(ClassLibrary4.RemoteUserEarth and ClassLibrary4.RemoteUserEarth).

I then tried all combinations of defines to make this work and kept
coming up with compiler errors - mainly "Cannot Implicitly assign"
errors.

I came closest with:

ClassLibrary4.RemoteUserEarth.RemoteUserServiceService
remoteUserServiceEarth = new
ClassLibrary4.RemoteUserEarth.RemoteUserServiceService();

ClassLibrary4.RemoteUserSaturn.RemoteUserServiceService
remoteUserServiceSaturn = new
ClassLibrary4.RemoteUserSaturn.RemoteUserServiceService();

object remoteUserService;

remoteUserService =
(ClassLibrary4.RemoteUserSaturn.RemoteUserServiceService)remoteUserServiceTfs;

This compiles fine, but I can't use the remoteUserService in my code as
it is an object.

ruDataBean = remoteUserService.fetchRemoteUserInfo(
userID,
"swpays",
"10.0.0.25",
"C", //Client (employer)
sessionID);

This gives me an error "'object' does not contain a definition for
'fetchRemoteUserInfo'".

What I am trying to do is get remoteUserService be the generic class
that I can using throughout my code. I don't want to create multiple
instances of the same code when the only difference is the machine I
point to. If I then have to set up a 3rd machine, I would have
recreate all my code again for the 3rd machine. I would much rather
just set up another variable, such as remoteUserServiceMars which I
just assign to remoteUserService when I point to that machine.

Can this be done?

Thanks,

Tom
 
V

Vijay

Tshad.. did u get this to work??

VJ

tshad said:
The webservices are created by another company that does our software to
access their functions. These are written in Java.

The error I get is (first line is the important one):
**********************************************************************************************************
System.InvalidOperationException: There is an error in XML document (43,
19). ---> System.InvalidCastException: Cannot assign object of type
System.String[][] to an object of type System.String[].
at
Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read3_RemoteUserDataBean()
at
System.Xml.Serialization.XmlSerializationReader.ReadReferencingElement(String
name, String ns, Boolean elementCanBeType, String& fixupReference)
at
System.Xml.Serialization.XmlSerializationReader.ReadReferencedElements()
at
Microsoft.Xml.Serialization.GeneratedAssembly.XmlSerializationReader1.Read6_fetchRemoteUserInfoResponse()
--- End of inner exception stack trace ---
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader
xmlReader, String encodingStyle, XmlDeserializationEvents events)
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader
xmlReader, XmlDeserializationEvents events)
at System.Xml.Serialization.XmlSerializer.Deserialize(XmlReader
xmlReader)
at
System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage
message, WebResponse response, Stream responseStream, Boolean asyncCall)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String
methodName, Object[] parameters)
at
ClassLibrary4.RemoteUser.RemoteUserServiceService.fetchRemoteUserInfo(String
in0, String in1, String in2, String in3, String in4)
at MyFunctions.NewHire.NewHireLogon(String sessionID)
at MyFunctions.NewHire..ctor()
at TestDll.Class1.Main(String[] args) in
c:\vsprojects\testdll\class1.cs:line 24
********************************************************************************************************************

This says I need to go into the Proxy (web reference.cs) code that VS
creates. Part of the code looks like:

********************************************************************************************
[System.Xml.Serialization.SoapTypeAttribute("RemoteUserDataBean",
"com.fwdco.wsbeans")]

public class RemoteUserDataBean{


/// <remarks/>

public string employeeId;


/// <remarks/>

public string[] employerList;


/// <remarks/>

public string ipAddress;


/// <remarks/>

public string password;


/// <remarks/>

public string peoContactEmail;


/// <remarks/>

public string userName;


/// <remarks/>

public string valid;

}

**********************************************************************************************

The problem is the emailList (in this case):

public string[] employerList;


it should be

public string[][] employerList;

Whenever I add one of these web services I have to find all these
variables and change them to make them work. You have to know which ones
are multi-dimensional as some are not and the [] is correct.

Tom

Vijay said:
The webservices that shipped with 1.1 or in parallel is what i am
using... There are certain datatypes that it will not understand.. like I
can't send a DataTable as a parameter, have to wrap it in a DataSet and
send it... Maybe the string[][] is a problem.. I have not tried that
parameter.. if you get a error when adding or creating object? what is
the error message can you post it?

Vijay

tshad said:
Tshad,

Changing URL to connect to different webservices is the best and easy
way..I do it all the time and it works great, we connect to different
servers also.. Could you post a sample of your problem in ability to
connect to different URL.

I tried that using the following:

remoteUserService.Url =
http://10.0.0.25:8080/data/services/RemoteUserService;

newHireService.Url = http://10.0.0.25:8080/data/services/newHireService;

employeeTaxService.Url =
http://10.0.0.25:8080/data/services/employeeTaxService;

This worked for the first one, but not the second one. These were
written in Java, and we do have a problem with creating the proxy when
using multi-dimensional strings ([][]).

I don't know if this is the case, but what I am trying to do is just
create all the web service Object and then create generic object that I
change to whichever service I need to access.

I just know how to get this to work. I thought I had it finally setting
up the generic service as an object and I seem to be able to assign the
actual service to it, but I can't seem to access the methods (and I
assume the properties).

Is there a way to make this method work?

Thanks,

Tom

Vijay

This is a little complicated to explain but I have some web services
on a machine that work great.

The problem is that I have run into a situation where I need to set up
my program to access one or another (could also be 3) different web
servers to use these Web Services. The Web Services are identical on
all the machines. I tried just changing the URL of the Web Services
and cannot make it work. I then decided to create 2 identical web
services (one for each machine) and then use a generic type to use in
my code.

The 2 web Servers are Earth and Saturn.

I originally had a Web Service called RemoteUserService, which has a
method fetchRemoteUserInfo.

To make this work I created 2 web services and called them
RemoteUserEarth and RemoteUserSaturn. Both Services are identical
except for the URL they point to and their Namespaces
(ClassLibrary4.RemoteUserEarth and ClassLibrary4.RemoteUserEarth).

I then tried all combinations of defines to make this work and kept
coming up with compiler errors - mainly "Cannot Implicitly assign"
errors.

I came closest with:

ClassLibrary4.RemoteUserEarth.RemoteUserServiceService
remoteUserServiceEarth = new
ClassLibrary4.RemoteUserEarth.RemoteUserServiceService();

ClassLibrary4.RemoteUserSaturn.RemoteUserServiceService
remoteUserServiceSaturn = new
ClassLibrary4.RemoteUserSaturn.RemoteUserServiceService();

object remoteUserService;

remoteUserService =
(ClassLibrary4.RemoteUserSaturn.RemoteUserServiceService)remoteUserServiceTfs;

This compiles fine, but I can't use the remoteUserService in my code
as it is an object.

ruDataBean = remoteUserService.fetchRemoteUserInfo(
userID,
"swpays",
"10.0.0.25",
"C", //Client (employer)
sessionID);

This gives me an error "'object' does not contain a definition for
'fetchRemoteUserInfo'".

What I am trying to do is get remoteUserService be the generic class
that I can using throughout my code. I don't want to create multiple
instances of the same code when the only difference is the machine I
point to. If I then have to set up a 3rd machine, I would have
recreate all my code again for the 3rd machine. I would much rather
just set up another variable, such as remoteUserServiceMars which I
just assign to remoteUserService when I point to that machine.

Can this be done?

Thanks,

Tom
 
T

tshad

No, it is getting very frustrating.

I think I have a better example, to show what I want to do.

If I have the following File with 3 Namespaces:
*****************************************
using System;

namespace News1
{
public class NewsItem
{
public string Headline = "This is News1.NewsItem.Headline";
}

public class NewsItemModules : NewsItem
{
public string GetNewsItem()
{
return Headline;
}
}
}
namespace News2
{
public class NewsItem
{
public string Headline = "This is News2.NewsItem.Headline";
}

public class NewsItemModules : NewsItem
{
public string GetNewsItem()
{
return Headline;
}
}
}
namespace News3
{
public class NewsItem
{
public string Headline = "This is News3.NewsItem.Headline";
}

public class NewsItemModules : NewsItem
{
public string GetNewsItem()
{
return Headline;
}
}
}
******************************************

These are identical namespaces (except for the string - but the structure is
all the same).

Now I have the following:

************************************************************************
using System;
using News1;
using News2;
using News3;

namespace MultiNamespaces
{
class Class1
{
static NewsItemModules theHeadline;

[STAThread]
static void Main(string[] args)
{
theHeadline = new NewsItemModules();
displayHeadline();
Console.WriteLine("Press any key to exit!");
Console.ReadLine();
}

static void displayHeadline()
{
Console.WriteLine(theHeadline.GetNewsItem());
}
}
}
*************************************************************************

I was having a problem getting the code to work until I used static, but
that is another issue.

If you comment out:

using News2;
using News3;

This works fine.

But what I want to do is set up a global variable (theHeadline).

I then want to instatiate the variable theHeadline based on some value
passed so that you would have something like:

if (x = 1)
{
theHeadline = new news1.NewsItemModules();
}

if (x = 2)
{
theHeadline = new news2.NewsItemModules();
}

if (x = 2)
{
theHeadline = new news2.NewsItemModules();
}

From that point all the functions in the class should be able to access the
properties and methods in theHeadline.

I was looking at maybe using a generic namespace/class where one of my
defined classes can override it or maybe an interface.

The problem is you apparently can't set it to one of the namespaces/classes
and then assign it to another class. If you were to do something like:
****************************************************
class Class1
{
static News1.NewsItemModules theHeadline;

[STAThread]
static void Main(string[] args)
{
theHeadline = new News1.NewsItemModules();
theHeadline = new News2.NewsItemModules();
****************************************************

This would give you a compiler error of:

Cannot implicitly convert type 'News2.NewsItemModules' to
'News1.NewsItemModules'

You also have to keep in mind that I have no access to the namespaces
(news1,news2,news3). These were written my someone else. I just know what
the methods are.

Hopefully, this explains what I am trying to do. Took awhile to put it
together.

Thanks,

Tom
 
B

Bill Butler

Hopefully, this explains what I am trying to do. Took awhile to put it together.

Try something like this:
I intentionally made the external services have different methods

----------------------------------------------------
// represents some external feed out of your control
namespace Fox
{
public class NewsClient
{
public string GetHeadLine()
{
return "FoxHeadLine";
}
}
}
----------------------------------------------------
// represents some external feed out of your control
namespace CNN
{
public class NewsTicker
{
public string GimmeTheNews()
{
return "CNNHeadLine";
}
}
}
----------------------------------------------------
// In house stuff that wraps the external stuff
namespace News
{
public interface INewsFeed
{
string GetNewsItem();
}

// This can be in the News namespace or anywhere else
public class FoxNewsFeed : INewsFeed
{
private Fox.NewsClient news = new Fox.NewsClient();

public string GetNewsItem()
{
return news.GetHeadLine();;
}
}

// This can be in the News namespace or anywhere else
public class CNNNewsFeed : INewsFeed
{
private CNN.NewsTicker news = new CNN.NewsTicker();

public string GetNewsItem()
{
return news.GimmeTheNews();;
}
}
}

-----------------------------------------------------------
// Test harness

using System;
using News;

namespace MultiNamespaces
{
class Class1
{
static INewsFeed theHeadline;

static void Main(string[] args)
{
theHeadline = new FoxNewsFeed();
displayHeadline();
theHeadline = new CNNNewsFeed();
displayHeadline();
}

static void displayHeadline()
{
Console.WriteLine(theHeadline.GetNewsItem());
}
}
}

Good Luck
Bill
 
L

Lucian Wischik

tshad said:
I then want to instatiate the variable theHeadline based on some value
passed so that you would have something like:
if (x = 1) theHeadline = new news1.NewsItemModules();
else if (x = 2) theHeadline = new news2.NewsItemModules();
You also have to keep in mind that I have no access to the namespaces
(news1,news2,news3). These were written my someone else. I just know what
the methods are.

So you can't change the original classes, I suppose. In that case what
you need is "Dynamic Dispatch". This is how other languages like
Python and Smalltalk work. It's not how statically-typed languages
like C# work. You can achieve the same dynamic-dispatch effect,
though, through reflection:

using System.Reflection;

class DynamicDispatcher
{ object Modules;
public DynamicDispatcher(object modules) {Modules=modules;}

public string GetNewsItem()
{ MethodInfo[] mis =
Modules.GetType().GetMethods(BindingFlags.Public|BindingFlags.Instance);
foreach (MethodInfo mi in mis)
{ if (mi.Name=="GetNewsItem" && mi.ReturnType==typeof(string) &&
mi.GetParameters().Length==0) return mi.Invoke(Modules,null) as
string;
}
throw new NotImplementedException("GetNewsItem");
}
}


Then call it like this:

if (x==1) theHeadline = new DynamicDispatch(new
News1.NewsItemModules());
else if (x==2) theHeadline = new DynamicDispatch(new
News2.NewsItemModules());
else theHeadline = new DynamicDispatch(new News3.NewsItemModules());
 
T

tshad

This looks like what I am looking for.

I was able to start to get this to work.

I was having a problem with parameters, however.

In your example, how would you change it so that the 2 actual methods are
something like:

public string GetHeadLine(string a, string b, int c)
and
public string GimmeTheNews(string a, string b, int c)

I was getting an error saying there are no occurrences with 0 parameters,
but couldn't get the interface section set up correctly.

Also, why do you have 2 semicolons after "return news.GetHeadLine();;"?

Thanks,

Tom

Bill Butler said:
Hopefully, this explains what I am trying to do. Took awhile to put it
together.

Try something like this:
I intentionally made the external services have different methods

----------------------------------------------------
// represents some external feed out of your control
namespace Fox
{
public class NewsClient
{
public string GetHeadLine()
{
return "FoxHeadLine";
}
}
}
----------------------------------------------------
// represents some external feed out of your control
namespace CNN
{
public class NewsTicker
{
public string GimmeTheNews()
{
return "CNNHeadLine";
}
}
}
----------------------------------------------------
// In house stuff that wraps the external stuff
namespace News
{
public interface INewsFeed
{
string GetNewsItem();
}

// This can be in the News namespace or anywhere else
public class FoxNewsFeed : INewsFeed
{
private Fox.NewsClient news = new Fox.NewsClient();

public string GetNewsItem()
{
return news.GetHeadLine();;
}
}

// This can be in the News namespace or anywhere else
public class CNNNewsFeed : INewsFeed
{
private CNN.NewsTicker news = new CNN.NewsTicker();

public string GetNewsItem()
{
return news.GimmeTheNews();;
}
}
}

-----------------------------------------------------------
// Test harness

using System;
using News;

namespace MultiNamespaces
{
class Class1
{
static INewsFeed theHeadline;

static void Main(string[] args)
{
theHeadline = new FoxNewsFeed();
displayHeadline();
theHeadline = new CNNNewsFeed();
displayHeadline();
}

static void displayHeadline()
{
Console.WriteLine(theHeadline.GetNewsItem());
}
}
}

Good Luck
Bill
 
T

tshad

Never mind on the parameters, I figured that out.

But not the ;;.

I am having a problem with passing back a class, however. I am going to
modify the example and see if I can make it happen there.

In a nutshell the error I am getting is:

C:\VSProjects\ClassLibrary4\FWWebServices.cs(14): Cannot implicitly convert
type 'ClassLibrary4.RemoteUserEarth.RemoteUserDataBean' to
'FWWebServices.RemoteUserDataBean' and
'ClassLibrary4.RemoteUserEarth.RemoteUserDataBean' is the exact same class
but in the external namespace.

I assume I would have to setup an inteface for this also, just not sure how
to do it.

Thanks,

Tom

Where RemoteUserDataBean is the Class in my interface section and
tshad said:
This looks like what I am looking for.

I was able to start to get this to work.

I was having a problem with parameters, however.

In your example, how would you change it so that the 2 actual methods are
something like:

public string GetHeadLine(string a, string b, int c)
and
public string GimmeTheNews(string a, string b, int c)

I was getting an error saying there are no occurrences with 0 parameters,
but couldn't get the interface section set up correctly.

Also, why do you have 2 semicolons after "return news.GetHeadLine();;"?

Thanks,

Tom

Bill Butler said:
Hopefully, this explains what I am trying to do. Took awhile to put it
together.

Try something like this:
I intentionally made the external services have different methods

----------------------------------------------------
// represents some external feed out of your control
namespace Fox
{
public class NewsClient
{
public string GetHeadLine()
{
return "FoxHeadLine";
}
}
}
----------------------------------------------------
// represents some external feed out of your control
namespace CNN
{
public class NewsTicker
{
public string GimmeTheNews()
{
return "CNNHeadLine";
}
}
}
----------------------------------------------------
// In house stuff that wraps the external stuff
namespace News
{
public interface INewsFeed
{
string GetNewsItem();
}

// This can be in the News namespace or anywhere else
public class FoxNewsFeed : INewsFeed
{
private Fox.NewsClient news = new Fox.NewsClient();

public string GetNewsItem()
{
return news.GetHeadLine();;
}
}

// This can be in the News namespace or anywhere else
public class CNNNewsFeed : INewsFeed
{
private CNN.NewsTicker news = new CNN.NewsTicker();

public string GetNewsItem()
{
return news.GimmeTheNews();;
}
}
}

-----------------------------------------------------------
// Test harness

using System;
using News;

namespace MultiNamespaces
{
class Class1
{
static INewsFeed theHeadline;

static void Main(string[] args)
{
theHeadline = new FoxNewsFeed();
displayHeadline();
theHeadline = new CNNNewsFeed();
displayHeadline();
}

static void displayHeadline()
{
Console.WriteLine(theHeadline.GetNewsItem());
}
}
}

Good Luck
Bill
 
T

tshad

Here is the new problem in the sample I had. I modified it like your
example and it worked fine when the return value was a string.

My problem is the external classes have a class that they are defining and
returning. This class is exactly the same in each Namespace, just like the
method was.

I am not sure if I need to create a new interface or do I put the class in
the original interface.

Here is the code and the error I get is:

C:\VSProjects\MultiNamespaces\Class3.cs(30): Cannot implicitly convert type
'News3.NewsDataBean' to 'string'

which at this point makes sense since the interface has the return a string,
but the external functions return a class (NewsDataBean). I obviously have
to change the string returns to a generic class.

class1.cs The program that uses the classes
**************************************************************************
using System;
using News;

namespace MultiNamespaces
{
class Class1
{
static INewsFeed theHeadline;

[STAThread]
static void Main(string[] args)
{
theHeadline = new FoxNewsFeed();
displayHeadline();
theHeadline = new CNNNewsFeed();
displayHeadline();
theHeadline = new ABCNewsFeed();
displayHeadline();

Console.WriteLine("Press any key to exit!");
Console.ReadLine();
}

static void displayHeadline()
{
Console.WriteLine(theHeadline.GetNewsItem("first","second","third"));
}
}
}
**************************************************************************

class2.cs The external Namespaces/Classes
**************************************************************************
using System;

namespace News1
{
public class NewsItem
{
public string Headline = "This is News1.NewsItem.Headline";
}

public class NewsItemModules : NewsItem
{
public NewsDataBean GetNewsItem(string a,string b,string c)
{
NewsDataBean NewsDB = new NewsDataBean();
NewsDB.final = a + " " + b + " " + c + " " + Headline;
return NewsDB;
}
}
public class NewsDataBean : NewsDataBean2
{
public string final;
}
public class NewsDataBean2
{
public string something;
}
}
namespace News2
{
public class NewsItem
{
public string Headline = "This is News2.NewsItem.Headline";
}

public class NewsItemModules : NewsItem
{
public NewsDataBean GetNewsItem(string a,string b,string c)
{
NewsDataBean NewsDB = new NewsDataBean();
NewsDB.final = a + " " + b + " " + c + " " + Headline;
return NewsDB;
}
}
public class NewsDataBean : NewsDataBean2
{
public string final;
}
public class NewsDataBean2
{
public string something;
}
}
namespace News3
{
public class NewsItem
{
public string Headline = "This is News3.NewsItem.Headline";
}

public class NewsItemModules : NewsItem
{
public NewsDataBean GetNewsItem(string a,string b,string c)
{
NewsDataBean NewsDB = new NewsDataBean();
NewsDB.final = a + " " + b + " " + c + " " + Headline;
return NewsDB;
}
}
public class NewsDataBean : NewsDataBean2
{
public string final;
}
public class NewsDataBean2
{
public string something;
}
}
**************************************************************************

class3.cs My interface that uses the external Namespaces
**************************************************************************
using System;

namespace News
{
public interface INewsFeed
{
string GetNewsItem(string a, string b, string c);
}
public class FoxNewsFeed : INewsFeed
{
private News1.NewsItemModules news = new News1.NewsItemModules();
public string GetNewsItem(string a,string b, string c)
{
return news.GetNewsItem(a,b,c);;
}
}
public class CNNNewsFeed : INewsFeed
{
private News2.NewsItemModules news = new News2.NewsItemModules();
public string GetNewsItem(string a,string b, string c)
{
return news.GetNewsItem(a,b,c);;
}
}
public class ABCNewsFeed : INewsFeed
{
private News3.NewsItemModules news = new News3.NewsItemModules();
public string GetNewsItem(string a,string b, string c)
{
return news.GetNewsItem(a,b,c);;
}
}
}
**************************************************************************

Thanks,

Tom

tshad said:
Never mind on the parameters, I figured that out.

But not the ;;.

I am having a problem with passing back a class, however. I am going to
modify the example and see if I can make it happen there.

In a nutshell the error I am getting is:

C:\VSProjects\ClassLibrary4\FWWebServices.cs(14): Cannot implicitly
convert type 'ClassLibrary4.RemoteUserEarth.RemoteUserDataBean' to
'FWWebServices.RemoteUserDataBean' and
'ClassLibrary4.RemoteUserEarth.RemoteUserDataBean' is the exact same class
but in the external namespace.

I assume I would have to setup an inteface for this also, just not sure
how to do it.

Thanks,

Tom

Where RemoteUserDataBean is the Class in my interface section and
tshad said:
This looks like what I am looking for.

I was able to start to get this to work.

I was having a problem with parameters, however.

In your example, how would you change it so that the 2 actual methods are
something like:

public string GetHeadLine(string a, string b, int c)
and
public string GimmeTheNews(string a, string b, int c)

I was getting an error saying there are no occurrences with 0 parameters,
but couldn't get the interface section set up correctly.

Also, why do you have 2 semicolons after "return news.GetHeadLine();;"?

Thanks,

Tom

Bill Butler said:
<snip the example>

Hopefully, this explains what I am trying to do. Took awhile to put it
together.

Try something like this:
I intentionally made the external services have different methods

----------------------------------------------------
// represents some external feed out of your control
namespace Fox
{
public class NewsClient
{
public string GetHeadLine()
{
return "FoxHeadLine";
}
}
}
----------------------------------------------------
// represents some external feed out of your control
namespace CNN
{
public class NewsTicker
{
public string GimmeTheNews()
{
return "CNNHeadLine";
}
}
}
----------------------------------------------------
// In house stuff that wraps the external stuff
namespace News
{
public interface INewsFeed
{
string GetNewsItem();
}

// This can be in the News namespace or anywhere else
public class FoxNewsFeed : INewsFeed
{
private Fox.NewsClient news = new Fox.NewsClient();

public string GetNewsItem()
{
return news.GetHeadLine();;
}
}

// This can be in the News namespace or anywhere else
public class CNNNewsFeed : INewsFeed
{
private CNN.NewsTicker news = new CNN.NewsTicker();

public string GetNewsItem()
{
return news.GimmeTheNews();;
}
}
}

-----------------------------------------------------------
// Test harness

using System;
using News;

namespace MultiNamespaces
{
class Class1
{
static INewsFeed theHeadline;

static void Main(string[] args)
{
theHeadline = new FoxNewsFeed();
displayHeadline();
theHeadline = new CNNNewsFeed();
displayHeadline();
}

static void displayHeadline()
{
Console.WriteLine(theHeadline.GetNewsItem());
}
}
}

Good Luck
Bill
 
B

Bill Butler

tshad said:
Never mind on the parameters, I figured that out.

But not the ;;.

Typo...Sorry

<snip>

I will respond to the rest after I eat dinner :^)

Bill
 
B

Bill Butler

Hi Tom,

First a few comments

Lets's step back for a second.
If the Web services on the 3 machines a identical, then you *should* be able to simply change the
URL in order to point to another identical service. You mentioned that you couldn't get this to
work, but you didn't elaborate.
I would invest some effort in this direction, as it would make your code cleaner in the long run. It
also makes sense that if the only difference between 3 Web Services is their URL, then they should
be represented by the same class. I don't mean classes with identical structure in different
namespaces. I mean the *same* class.

However, if you wish to go forward
change this
public string GetNewsItem(string a,string b, string c)
{
return news.GetNewsItem(a,b,c);
}

to this
public string GetNewsItem(string a,string b, string c)
{
News3.NewsDataBean bean = news.GetNewsItem(a,b,c);
return bean.final;
}


I am a bit curious as to the reason for your inheritance structure
Why do you need a NewsItem and a NewsItemModules class?
Why do you need a NewsDataBean and a NewsDataBean2?


Bill
 
T

tshad

Bill Butler said:
Hi Tom,

First a few comments

Lets's step back for a second.
If the Web services on the 3 machines a identical, then you *should* be
able to simply change the URL in order to point to another identical
service. You mentioned that you couldn't get this to work, but you didn't
elaborate.

Actually, this was what I originally tried to do.

The Web Services are written in Java and we just have access to them. But
MS seems to have a problem with the Proxy that it builds from the wsdl. We
have another problem with multiple defined arrays (string [][]), it only
defines it as string[]. I need to manually change the proxy wherever these
show up. It may be related to the Java/MS problem.

In this case, I have 2 machines 10.0.0.3 and 10.0.0.25 both running apache
tomcat. In my program, I can add the web services from either machine with
no problem. The first service it finds fine, but the 2nd one gives us an
error and all I do is change the URL. Following is how it is set up.

RemoteUserService works fine.

But when I call newHireService.readNewHire I get the following error:

System.Web.Services.Protocols.SoapException: The AXIS engine could not find
a target service to invoke! targetService is newHireService at
System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage
message, WebResponse response, Stream responseStream, Boolean asyncCall)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String
methodName, Object[] parameters)
at ClassLibrary4.NewHire.NewHireServiceService.readNewHire(String in0,
String in1, String in2)
at MyFunctions.NewHire..ctor()
at TestDll.Class1.Main(String[] args) in
c:\vsprojects\testdll\class1.cs:line 24

It can't seem to find the newHireService.

Here is the section of code that changes the URL and the code that calls the
2 services

*********************************************************************************************
RemoteUserServiceService remoteUserService = new
RemoteUserServiceService();
NewHireServiceService newHireService = new NewHireServiceService();

RemoteUserDataBean ruDataBean;
NewHireDataBean nhDataBean;

public NewHire()
{
sessionID = "150";

remoteUserService.Url =
"http://10.0.0.25:8080/data_connect/services/RemoteUserService";
newHireService.Url =
"http://10.0.0.25:8080/data_connect/services/newHireService";

NewHireLogon(sessionID);
if (errorCode == 0)
{
nhDataBean = newHireService.readNewHire(
companyNumber,
userID,
sessionID);


.... other code.


private void NewHireLogon(string sessionID)
{
ruDataBean = remoteUserService.fetchRemoteUserInfo(
userID,
"sw",
"",
"C", //Client (employer)
sessionID);

errorCode = ruDataBean.errorCode;
errorMessage = ruDataBean.errorMessage;
}
**************************************************************************************
As you can see, I set the URL, then I call both services. 1st one works and
2nd one gives the error.

I am not sure why one works and one doesn't. If I comment out the 2 lines
that change the URLs, it works fine. I assume the URLs are correct since it
finds the first one (RemoteUserServer).
I would invest some effort in this direction, as it would make your code
cleaner in the long run. It also makes sense that if the only difference
between 3 Web Services is their URL, then they should be represented by
the same class. I don't mean classes with identical structure in different
namespaces. I mean the *same* class.

I agree. It would be cleaner and would be the one I would prefer to use. I
was hoping to wrap the services in a generic one and just call the Generic
functions (as you set up with the interfaces). The only other way is to
create copies of all the calls and call one function when I need to hit one
server and the other function when I need the other servers services. In
essence, what you did with the interfaces.
However, if you wish to go forward
change this
public string GetNewsItem(string a,string b, string c)
{
return news.GetNewsItem(a,b,c);
}

to this
public string GetNewsItem(string a,string b, string c)
{
News3.NewsDataBean bean = news.GetNewsItem(a,b,c);
return bean.final;
}


I am a bit curious as to the reason for your inheritance structure
Why do you need a NewsItem and a NewsItemModules class?
Why do you need a NewsDataBean and a NewsDataBean2?

I did get the argument problem to work.

I was setting up 2 classes in one namespace just to have one class call
another class in the same namespace - as the web service does.

The DataBeans are non standard types (classes). The DataBean in Java is
just a structure. In all the examples I have seen, the returns are always
strings or ints. There is only one string type and one int type for
everyone. The Databeans are also identical, but they aren't standard types.
When you create a proxy with a class, it recreates the class in each web
service (it doesn't do that for strings).

So you can return just NewsDataBean. It has to be class.NewsDataBean or
namespace.class.NewsDataBean (not sure which). But they are different
(strings aren't - as in your example).

If I was only going to use the newsDataBean inside the classes, there
wouldn't be a problem (as in the NewsItem). But I need to get access to the
properties in the DataBean from the program that calls the Services.

In our example I am doing:

Console.WriteLine(theHeadline.GetNewsItem("first","second","third"));

This works because I am returning a string frin GetNewsItem.

But I need to return a Structure (DataBean) which could have strings, ints,
return values, error codes, error messages, etc.

I need to be able to do something like

NewDataBean = theHeadline.GetNewsItem("first","second","third");
Console.WriteLine(NewDataBean.something)

Maybe this is getting too convoluted.

Thanks,

Tom
 
B

Bill Butler

Comments Inline
tshad said:
Bill Butler said:
Hi Tom,

First a few comments

Lets's step back for a second.
If the Web services on the 3 machines a identical, then you *should* be able to simply change the
URL in order to point to another identical service. You mentioned that you couldn't get this to
work, but you didn't elaborate.

Actually, this was what I originally tried to do.

The Web Services are written in Java and we just have access to them. But MS seems to have a
problem with the Proxy that it builds from the wsdl. We have another problem with multiple
defined arrays (string [][]), it only defines it as string[]. I need to manually change the proxy
wherever these show up. It may be related to the Java/MS problem.

In this case, I have 2 machines 10.0.0.3 and 10.0.0.25 both running apache tomcat. In my program,
I can add the web services from either machine with no problem. The first service it finds fine,
but the 2nd one gives us an error and all I do is change the URL. Following is how it is set up.

RemoteUserService works fine.

But when I call newHireService.readNewHire I get the following error:

System.Web.Services.Protocols.SoapException: The AXIS engine could not find a target service to
invoke! targetService is newHireService at
System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage message,
WebResponse response, Stream responseStream, Boolean asyncCall)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[]
parameters)
at ClassLibrary4.NewHire.NewHireServiceService.readNewHire(String in0, String in1, String in2)
at MyFunctions.NewHire..ctor()
at TestDll.Class1.Main(String[] args) in c:\vsprojects\testdll\class1.cs:line 24

It can't seem to find the newHireService.

Here is the section of code that changes the URL and the code that calls the 2 services

*********************************************************************************************
RemoteUserServiceService remoteUserService = new RemoteUserServiceService();
NewHireServiceService newHireService = new NewHireServiceService();

RemoteUserDataBean ruDataBean;
NewHireDataBean nhDataBean;

public NewHire()
{
sessionID = "150";

remoteUserService.Url = "http://10.0.0.25:8080/data_connect/services/RemoteUserService";
newHireService.Url = "http://10.0.0.25:8080/data_connect/services/newHireService";

Shouldn't that be "NewHireService"? I am not sure if case matters???

NewHireLogon(sessionID);
if (errorCode == 0)
{
nhDataBean = newHireService.readNewHire(
companyNumber,
userID,
sessionID);


... other code.


private void NewHireLogon(string sessionID)
{
ruDataBean = remoteUserService.fetchRemoteUserInfo(
userID,
"sw",
"",
"C", //Client (employer)
sessionID);

errorCode = ruDataBean.errorCode;
errorMessage = ruDataBean.errorMessage;
}
**************************************************************************************
As you can see, I set the URL, then I call both services. 1st one works and 2nd one gives the
error.

I am not sure why one works and one doesn't. If I comment out the 2 lines that change the URLs,
it works fine. I assume the URLs are correct since it finds the first one (RemoteUserServer).


I agree. It would be cleaner and would be the one I would prefer to use. I was hoping to wrap
the services in a generic one and just call the Generic functions (as you set up with the
interfaces). The only other way is to create copies of all the calls and call one function when I
need to hit one server and the other function when I need the other servers services. In essence,
what you did with the interfaces.

Absolutely, it would be much nicer.
The solution that I was presenting Is more approriate when you have Feeds from dissimilar sources.
When the Feeds are identical it makes more sense to simply have each feed be a different instance of
the same class.
I did get the argument problem to work.

I was setting up 2 classes in one namespace just to have one class call another class in the same
namespace - as the web service does.

The DataBeans are non standard types (classes). The DataBean in Java is just a structure. In all
the examples I have seen, the returns are always strings or ints. There is only one string type
and one int type for everyone. The Databeans are also identical, but they aren't standard types.
When you create a proxy with a class, it recreates the class in each web service (it doesn't do
that for strings).

So you can return just NewsDataBean. It has to be class.NewsDataBean or
namespace.class.NewsDataBean (not sure which). But they are different (strings aren't - as in
your example).

If I was only going to use the newsDataBean inside the classes, there wouldn't be a problem (as in
the NewsItem). But I need to get access to the properties in the DataBean from the program that
calls the Services.

In our example I am doing:

Console.WriteLine(theHeadline.GetNewsItem("first","second","third"));

This works because I am returning a string frin GetNewsItem.

But I need to return a Structure (DataBean) which could have strings, ints, return values, error
codes, error messages, etc.

I need to be able to do something like

NewDataBean = theHeadline.GetNewsItem("first","second","third");
Console.WriteLine(NewDataBean.something)

Maybe this is getting too convoluted.

This is the problem with the path we were walking down.
You would have a family classes with exactly the same structure, but no intrinsic relation between
them.
You *could* create Conversion routines for each of the beans that return a "commonBean". This is NOT
the ideal solution as it is NOT very expandible. Each additional "Identical" service would require a
set of new conversion routines.

The fact that NewHireServiceService works with the default URL, but not the changed URL sounds
suspicious.
Hopefully it is just the Case if the service name.


Good luck
Bill
 
T

tshad

Bill Butler said:
Comments Inline
tshad said:
Bill Butler said:
Hi Tom,

First a few comments

Lets's step back for a second.
If the Web services on the 3 machines a identical, then you *should* be
able to simply change the URL in order to point to another identical
service. You mentioned that you couldn't get this to work, but you
didn't elaborate.

Actually, this was what I originally tried to do.

The Web Services are written in Java and we just have access to them.
But MS seems to have a problem with the Proxy that it builds from the
wsdl. We have another problem with multiple defined arrays (string
[][]), it only defines it as string[]. I need to manually change the
proxy wherever these show up. It may be related to the Java/MS problem.

In this case, I have 2 machines 10.0.0.3 and 10.0.0.25 both running
apache tomcat. In my program, I can add the web services from either
machine with no problem. The first service it finds fine, but the 2nd
one gives us an error and all I do is change the URL. Following is how
it is set up.

RemoteUserService works fine.

But when I call newHireService.readNewHire I get the following error:

System.Web.Services.Protocols.SoapException: The AXIS engine could not
find a target service to invoke! targetService is newHireService at
System.Web.Services.Protocols.SoapHttpClientProtocol.ReadResponse(SoapClientMessage
message, WebResponse response, Stream responseStream, Boolean asyncCall)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String
methodName, Object[] parameters)
at ClassLibrary4.NewHire.NewHireServiceService.readNewHire(String in0,
String in1, String in2)
at MyFunctions.NewHire..ctor()
at TestDll.Class1.Main(String[] args) in
c:\vsprojects\testdll\class1.cs:line 24

It can't seem to find the newHireService.

Here is the section of code that changes the URL and the code that calls
the 2 services

*********************************************************************************************
RemoteUserServiceService remoteUserService = new
RemoteUserServiceService();
NewHireServiceService newHireService = new NewHireServiceService();

RemoteUserDataBean ruDataBean;
NewHireDataBean nhDataBean;

public NewHire()
{
sessionID = "150";

remoteUserService.Url =
"http://10.0.0.25:8080/data_connect/services/RemoteUserService";
newHireService.Url =
"http://10.0.0.25:8080/data_connect/services/newHireService";

Shouldn't that be "NewHireService"? I am not sure if case matters???

You're right!!!

That solved the URL problem. I am not sure why it has to be Caps - case is
normally not an issue when dealing with other web pages.

I would still like to get my other example to work, just so I understand the
problem and how to use Interfaces over and above what we see in normal
examples on the web or in my book.

Thanks,

Tom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top