Why C# downcast become always null? - c#

So here is my code,
public void CheckStatChal()
{
foreach (SpotUIBase menu in thisSpot.ownMenus)
{
if (menu.uiSort == SpotUISort.StatEvent)
{
if(menu != null)
Debug.Log("Menu name is "+menu.Name);
var statEvent = menu as StatEvent;
if (statEvent == null)
{
Debug.Log("Stat event is null, name is "+thisSpot.Name);
continue;
}
.......... [1]
public SpecialSpotClass thisSpot;
public abstract class SpecialSpotClass
{
public List<SpotUIBase> ownMenus = new List<SpotUIBase>();
....
public class SpotUIBase
{
public SpotUISort uiSort;
....
public class StatEvent : SpotUIBase
{
....
public enum SpotUISort{
Inn, Shop, Bar,
I am using Unity engine now.
So if run this code, I got
Debug.Log("Menu name is "+menu.Name); and
Debug.Log("Stat event is null, name is "+thisSpot.Name); both.
Why?
menu is not null, but after downcast it, it become null?
I don't understand this why.
So in this code, I want to execute [1] part below codes, but [statEvent] is null,
so all the code below does not called by (continue keyword)
Why downcast become null?
Help please.

So I googled and confirmed right Downcast method, and changed foreach to for syntax.
And solved.
Here is changed code.
for (int i = 0; i < thisSpot.ownMenus.Count; i++)
{
if (thisSpot.ownMenus[i].uiSort == SpotUISort.StatEvent)
{
thisSpot.ownMenus[i] = SpotUI.Instance.StatEvent;
var ownMenu = (StatEvent) thisSpot.ownMenus[i];
Debug.Log("own menu is "+ownMenu.Name);
if ((!ownMenu.StatChal1.nowCoolTime && ownMenu.StatChal1 != null)
|| ownMenu.StatChal1 == null)
{
StatChallenge.Instance.MakeStatChal(this, ref ownMenu.StatChal1);
Debug.Log(ownMenu.StatChal1.Name);
ownMenu.SetChalInfo(ownMenu.StatChal1, 1);
chal1 = ownMenu.StatChal1;
}

Related

Swashbuckle throws StackOverFlow exception when class have circular reference

I have a controller like below having circular reference in class B.
This is happening because Swashbuckle's jsonserilalizer's setting is set to
ReferenceLoopHandling = ReferenceLoopHandling.Error and I didn't find any way to override this setting.
I am using Swashbuckle 5.6.0 in an ASP.NET MVC application.
public class IssueController : ApiController
{
[HttpGet]
[Route("A")]
public A Get(A input)
{
return new A();
}
}
public class A
{
public virtual B prop1 { get; set; }
}
public class B
{
public virtual B Parent { get; set; }
}
In my case it turned out, that the Stackoverflow exception wasn't caused by the jsonserializer, but by the previous step (when the Swashbuckle schema gets created before json gets serialized). Circle References doesn't seem to work yet with Swashbuckle (in Swashbuckle for it seems to be fixed btw). To fix this, you have to copy the HandleFromUriParamsRecurseSave and add this (with the other filters) to the operations:
private static SwaggerDocument BuildSwaggerDocument()
{
...
var operationFilters = new List<IOperationFilter> {
new HandleFromUriParamsRecurseSave(20),
...
};
}
In the copied HandleFromUriParamsRecurseSave just add a maxrecurselength property, which fits your case and you shouldn't have the StackOverflow error any more:
private void ExtractAndAddQueryParams(
Schema sourceSchema,
string sourceQualifier,
bool? sourceRequired,
SchemaRegistry schemaRegistry,
ICollection<Parameter> operationParams)
{
foreach (var property in sourceSchema.properties)
{
...
var recurseCount = sourceQualifier.Count(t => t == '.');
if (schema.#ref != null && recurseCount < _maxRecurseLength)
{
ExtractAndAddQueryParams(schemaRegistry.Definitions[schema.#ref.Replace("#/definitions/", "")], sourceQualifier + ToCamelCase(property.Key) + ".", flag, schemaRegistry, operationParams);
}
else
{
...
}
}
}
}
A further workaround I tried, but unfortunately didn't solve the issue, was to add a stack and everytime I detected a loop, added the right schema definition just one time (maybe someone sees the problem):
private void ExtractAndAddQueryParams(
Stack<string> sourceSchemaNames,
Schema sourceSchema,
string sourceQualifier,
bool? sourceRequired,
SchemaRegistry schemaRegistry,
ICollection<Parameter> operationParams)
{
if (sourceSchemaNames.Count > _maxRecurseLength) {
return;
}
foreach (var property in sourceSchema.properties)
{
var schema = property.Value;
var readOnly = schema.readOnly;
if (readOnly != true)
{
var flag = sourceRequired == true && sourceSchema.required != null && sourceSchema.required.Contains(property.Key);
var recursionDetected = _disableRecursion && sourceSchemaNames.Contains(schema.#ref);
if (schema.#ref != null && !recursionDetected)
{
sourceSchemaNames.Push(schema.#ref);
ExtractAndAddQueryParams(sourceSchemaNames, schemaRegistry.Definitions[schema.#ref.Replace("#/definitions/", "")],
sourceQualifier + ToCamelCase(property.Key) + ".", flag, schemaRegistry,
operationParams);
sourceSchemaNames.Pop();
}
else
{
...
if (recursionDetected) {
partialSchema.type = "object";
partialSchema.#ref = schema.#ref;
}
operationParams.Add(partialSchema);
}
}
}
}
}

MvvmCross - How to Add Custom Modal Transition

I am working on a project using MvvmCross and Xamarin. I am trying to add a custom transition when presenting and dismissing my modal view. Currently I am presenting it this way:
[MvxModalPresentation(WrapInNavigationController = true, ModalPresentationStyle = UIModalPresentationStyle.Custom)]
public partial class MyView : MvxViewController
{
and dismissing it this way:
NavigationController.DismissModalViewController(true);
So I have my animation ready, but I am assuming that I need to set the transition delegate to the one I've created. How do I do this?
I am fairly new to MvvmCross, so any tips and tricks are very much appreciated. Thanks!
I Am not sure, what you actually want to achieve here.
If you are looking for syntax help. This should be something like this.
this.NavigationController.TransitioningDelegate = new MyOwnDelegate();
internal class MyOwnDelegate : IUIViewControllerTransitioningDelegate
{
public IntPtr Handle => throw new NotImplementedException();
public void Dispose()
{
//throw new NotImplementedException();
}
}
But normally people use, this one. I am also giving some syntax if that helps
this.NavigationController.Delegate = new NavigationControllerDelegate();
public class NavigationControllerDelegate : UINavigationControllerDelegate
{
public NavigationControllerDelegate(IntPtr handle) : base(handle)
{
}
public NavigationControllerDelegate()
{
}
public override IUIViewControllerAnimatedTransitioning GetAnimationControllerForOperation(UINavigationController navigationController, UINavigationControllerOperation operation, UIViewController fromViewController, UIViewController toViewController)
{
var fromVcConformA = fromViewController as ICustomTransition;
var fromVCConFromB = fromViewController as IWaterFallViewControllerProtocol;
var fromVCCConformc = fromViewController as IHorizontalPageViewControllerProtocol;
var toVcConformA = toViewController as ICustomTransition;
var toVCConfromB = toViewController as IWaterFallViewControllerProtocol;
var toVCCConformc = toViewController as IHorizontalPageViewControllerProtocol;
if ((fromVcConformA != null) && (toVcConformA != null) && ((fromVCConFromB != null && toVCCConformc != null) || (fromVCCConformc != null && toVCConfromB != null)))
{
var transition = new CustomTransition();
transition.presenting = operation == UINavigationControllerOperation.Pop;
return transition;
}
else
{
return null;
}
}
}

ArgumentOutOfRangeException despite boundary checks

I have created custom button in winforms in which i've added property with a list of custom class: List<Zasoby> and a method to add item to this list only when there is already item in that list that meets specific criteria (the lambda .where expression).
The class Zasob is serializable.
And in designer i add first Zasob to the list in this button like this:
bt01008xxx.Zasoby.Add(new Zasob { Lokalizacja = new Lokalizacja("01", "008", "000") });
..
public class ZasobSzczegolowoButton: Button, IAddZasoby
{
private List<Zasob> _zasoby = new List<Zasob>(); //{ new Zasob { Lokalizacja = new Lokalizacja("01", "001", "000") } };
[EditorBrowsable(EditorBrowsableState.Always)]
[Browsable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
[Bindable(true)]
public List<Zasob> Zasoby
{
get { return _zasoby; }
set
{
_zasoby = value;
if (_zasoby.Any()) BackColor = _zasoby.Sum(x => x.Ilosc) > 0 ? Color.Coral : Color.White;
}
}
public void AddZasoby(List<Zasob> zasoby)
{
var buton = Name;
if (_zasoby != null && _zasoby.Count != 0)
{
var szukaneZasoby =
zasoby?.Where(
x =>
x.Lokalizacja.ObszarKod == _zasoby[0].Lokalizacja.ObszarKod &&
x.Lokalizacja.Segment1 == _zasoby[0].Lokalizacja.Segment1);
if (szukaneZasoby == null) return;
Zasoby.Clear();
Zasoby.AddRange(szukaneZasoby);
}
}
}
...
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Enum | AttributeTargets.Delegate,Inherited = false)]
[ComVisible(true)]
public class Zasob : Attribute
{
public Towar Towar { get; set; }
public Magazyn Magazyn { get; set; }
public Lokalizacja Lokalizacja { get; set; }
public decimal Ilosc { get; set; }
}
Now whenever i try to use method AddZasoby i get System.ArgumentOutOfRangeException. I check the list for null and count items and in debug mode and it shoud exit method but still somehow ends up in the body of the method with the error. (please see the screenshot below)
Any idea what am i doing wrong?
You check the list correctly for the count but with the code Zasoby.Clear(); you clear those elements from the member variable _zasoby again.
Don't let it trick yourself: You're defining the Where()-clause before you clear the list but it will be executed afterwards! That's the trick with lambdas, the predicates you wrote in your Where()-lambda will just be executed as soon as it is evaluated.
This feature is called Deferred Execution, see the first example here.
To fix that, you can enforce the lambda to be executed immediately by calling ToArray() or ToList() before you clear your list like:
public void AddZasoby(List<Zasob> zasoby)
{
var buton = Name;
if (_zasoby != null && _zasoby.Count != 0)
{
var szukaneZasoby =
zasoby?.Where(
x =>
x.Lokalizacja.ObszarKod == _zasoby[0].Lokalizacja.ObszarKod &&
x.Lokalizacja.Segment1 == _zasoby[0].Lokalizacja.Segment1
).ToList(); // *** NOTE ME HERE ***
if (szukaneZasoby == null) return;
Zasoby.Clear();
Zasoby.AddRange(szukaneZasoby);
}
}
That should do the trick.

Create a generic type to find implementations of in a Resharper plugin

I'm writing a plugin for resharper which I want to use to navigate from a ConcreteCommand -> ConcreteCommandHandler where those types look like this
public class ConcreteCommand : ICommand
public class ConcreteCommandHandler : ICommandHandler<ConcreteCommand>
I've got as far as adding my navigation menu option when the cursor is on a ICommand instance/definition (currently only by checking if the name contains 'Command' and not 'CommandHandler'), and I think I have the code necessary to actually search for a type which inherits something, but my issue is that the only thing I actually have a type for is my ConcereteCommand and I need to create (or get a reference to) the generic type ICommandHandler<T> with T being the type the cursor is currently on.
So I have 2 things I still want to know:
How can I check if my IDeclaredElement is an implementation of a particular interface (ideally by specifying the full name in a string from config)?
How can I create a ITypeElement which is a generic type of a specific interface where I can set the generic type from my existing IDeclaredElements type, so I can then find classes which inherit this?
My existing code looks like this:
[ContextNavigationProvider]
public class CommandHandlerNavigationProvider : INavigateFromHereProvider
{
public IEnumerable<ContextNavigation> CreateWorkflow(IDataContext dataContext)
{
ICollection<IDeclaredElement> declaredElements = dataContext.GetData(DataConstants.DECLARED_ELEMENTS);
if (declaredElements != null || declaredElements.Any())
{
IDeclaredElement declaredElement = declaredElements.First();
if (IsCommand(declaredElement))
{
var solution = dataContext.GetData(JetBrains.ProjectModel.DataContext.DataConstants.SOLUTION);
yield return new ContextNavigation("This Command's &handler", null, NavigationActionGroup.Other, () => { GotToInheritor(solution,declaredElement); });
}
}
}
private void GotToInheritor(ISolution solution, IDeclaredElement declaredElement)
{
var inheritorsConsumer = new InheritorsConsumer();
SearchDomainFactory searchDomainFactory = solution.GetComponent<SearchDomainFactory>();
//How can I create the ITypeElement MyNameSpace.ICommandHandler<(ITypeElement)declaredElement> here?
solution.GetPsiServices().Finder.FindInheritors((ITypeElement)declaredElement, searchDomainFactory.CreateSearchDomain(solution, true), inheritorsConsumer, NullProgressIndicator.Instance);
}
private bool IsCommand(IDeclaredElement declaredElement)
{
//How can I check if my declaredElement is an implementation of ICommand here?
string className = declaredElement.ShortName;
return className.Contains("Command")
&& !className.Contains("CommandHandler");
}
}
Ok managed to work this out with a fair bit of pushing in the right direction from #CitizenMatt.
basically my solution looks like this (still needs some tidying up)
private static readonly List<HandlerMapping> HandlerMappings = new List<HandlerMapping>
{
new HandlerMapping("HandlerNavigationTest.ICommand", "HandlerNavigationTest.ICommandHandler`1", "HandlerNavigationTest"),
new HandlerMapping("HandlerNavTest2.IEvent", "HandlerNavTest2.IEventHandler`1", "HandlerNavTest2")
};
public IEnumerable<ContextNavigation> CreateWorkflow(IDataContext dataContext)
{
ICollection<IDeclaredElement> declaredElements = dataContext.GetData(DataConstants.DECLARED_ELEMENTS);
if (declaredElements != null && declaredElements.Any())
{
IDeclaredElement declaredElement = declaredElements.First();
ISolution solution = dataContext.GetData(JetBrains.ProjectModel.DataContext.DataConstants.SOLUTION);
ITypeElement handlerType = GetHandlerType(declaredElement);
if (handlerType != null)
{
yield return new ContextNavigation("&Handler", null, NavigationActionGroup.Other, () => GoToInheritor(solution, declaredElement as IClass, dataContext, handlerType));
}
}
}
private static ITypeElement GetHandlerType(IDeclaredElement declaredElement)
{
var theClass = declaredElement as IClass;
if (theClass != null)
{
foreach (IPsiModule psiModule in declaredElement.GetPsiServices().Modules.GetModules())
{
foreach (var handlerMapping in HandlerMappings)
{
IDeclaredType commandInterfaceType = TypeFactory.CreateTypeByCLRName(handlerMapping.HandledType, psiModule, theClass.ResolveContext);
ITypeElement typeElement = commandInterfaceType.GetTypeElement();
if (typeElement != null)
{
if (theClass.IsDescendantOf(typeElement))
{
IDeclaredType genericType = TypeFactory.CreateTypeByCLRName(handlerMapping.HandlerType, psiModule, theClass.ResolveContext);
ITypeElement genericTypeElement = genericType.GetTypeElement();
return genericTypeElement;
}
}
}
}
}
return null;
}
private static void GoToInheritor(ISolution solution, IClass theClass, IDataContext dataContext, ITypeElement genericHandlerType)
{
var inheritorsConsumer = new InheritorsConsumer();
var searchDomainFactory = solution.GetComponent<SearchDomainFactory>();
IDeclaredType theType = TypeFactory.CreateType(theClass);
IDeclaredType commandHandlerType = TypeFactory.CreateType(genericHandlerType, theType);
ITypeElement handlerTypeelement = commandHandlerType.GetTypeElement();
solution.GetPsiServices().Finder.FindInheritors(handlerTypeelement, searchDomainFactory.CreateSearchDomain(solution, true),
inheritorsConsumer, NullProgressIndicator.Instance);
var potentialNavigationPoints = new List<INavigationPoint>();
foreach (ITypeElement inheritedInstance in inheritorsConsumer.FoundElements)
{
IDeclaredType[] baseClasses = inheritedInstance.GetAllSuperTypes();
foreach (IDeclaredType declaredType in baseClasses)
{
if (declaredType.IsInterfaceType())
{
if (declaredType.Equals(commandHandlerType))
{
var navigationPoint = new DeclaredElementNavigationPoint(inheritedInstance);
potentialNavigationPoints.Add(navigationPoint);
}
}
}
}
if (potentialNavigationPoints.Any())
{
NavigationOptions options = NavigationOptions.FromDataContext(dataContext, "Which handler do you want to navigate to?");
NavigationManager.GetInstance(solution).Navigate(potentialNavigationPoints, options);
}
}
public class InheritorsConsumer : IFindResultConsumer<ITypeElement>
{
private const int MaxInheritors = 50;
private readonly HashSet<ITypeElement> elements = new HashSet<ITypeElement>();
public IEnumerable<ITypeElement> FoundElements
{
get { return elements; }
}
public ITypeElement Build(FindResult result)
{
var inheritedElement = result as FindResultInheritedElement;
if (inheritedElement != null)
return (ITypeElement) inheritedElement.DeclaredElement;
return null;
}
public FindExecution Merge(ITypeElement data)
{
elements.Add(data);
return elements.Count < MaxInheritors ? FindExecution.Continue : FindExecution.Stop;
}
}
And this allows me no navigate to multiple handlers if they exist. This currently relies on the interfaces for the handled type and the handler type being in the same assembly. But this seems reasonable enough for me at the moment.

partial constructor to remove initialization from getter

public partial class Class1
{
public ICollection<ContactNumber> ContactNumbers
{
get
{
List<ContactNumber> list = new List<ContactNumber>();
if (Contact != null)
{
if (Contact.Qualifier1 != null || Contact.Number1 != null)
list.Add(new ContactNumber { Qualifier = Contact.Qualifier1, Number = Contact.Number1 });
if (Contact.Qualifier2 != null || Contact.Number2 != null)
list.Add(new ContactNumber { Qualifier = Contact.Qualifier2, Number = Contact.Number2 });
if (Contact.Qualifier3 != null || Contact.Number3 != null)
list.Add(new ContactNumber { Qualifier = Contact.Qualifier3, Number = Contact.Number3 });
}
return list;
}
set
{
for (int i = 0; i < value.Count; i++)
{
ContactNumber cn = value.ElementAt(i);
switch (i)
{
case 0:
Contact.Qualifier1 = cn.Qualifier;
Contact.Number1 = cn.Number;
break;
case 1:
Contact.Qualifier2 = cn.Qualifier;
Contact.Number2 = cn.Number;
break;
case 2:
Contact.Qualifier3 = cn.Qualifier;
Contact.Number3 = cn.Number;
break;
case 3:
Contact.Qualifier4 = cn.Qualifier;
Contact.Number4 = cn.Number;
break;
}
//
// Manual changes to this file may cause unexpected behavior in your application.
// Manual changes to this file will be overwritten if the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
public partial class Class1
{
public Class1()
{
////
}
Can someone suggest to say to remove the initialization from the getter.
Where can I initialize it? There is a constructor already defined.
Is there like a partial constructor? Even using a partial constructore may not help. It should be partial Class1() in both classes and one of them is generated by default in EF 4.0
EDIT 2:
public virtual ObservableListSource<Adjustment> Adjustments { get; set; }
public class ObservableListSource<T> : ObservableCollection<T>, IListSource
where T : class
{
private IBindingList _bindingList;
bool IListSource.ContainsListCollection { get { return false; } }
IList IListSource.GetList()
{
return _bindingList ?? (_bindingList = this.ToBindingList());
}
}
public ICollection<ContactNumber> ContactNumbers
{
get
{
return list;
}
}
One needs COllectionchanged property implemented and one does not..?
OK, if I understand your questions right, you're asking the wrong question. You have a set of Contacts in a list and you want to return a list of all contacts that match of of the contacts subproperties.
I wouldn't use a property for that. Just make a method like this:
public List<Contact> FilterContacts(Contact con)
{
var copy = new List<Contact>();
foreach (Contact cn in Contacts)
{
if (cn.number == con.number)
copy.add(cn);
else
if (cn.name == con.name)
copy.add(cn);
}
return copy;
}
I guess this is what you mean. Might be I'm completely wrong about this, but if you rephrase your question to what you actually try to do, it's easier to help you.

Categories